get transcripts passing

This commit is contained in:
Mitchell Rosen 2024-07-23 13:45:16 -04:00
parent 4b68359e6e
commit 7506ae26b6
29 changed files with 405 additions and 419 deletions

View File

@ -1,8 +1,11 @@
module Unison.PrettyPrintEnvDecl.Names
( makePPED,
makeFilePPED,
makeCodebasePPED,
)
where
import Unison.Names (Names)
import Unison.PrettyPrintEnv.Names qualified as PPE
import Unison.PrettyPrintEnvDecl (PrettyPrintEnvDecl (PrettyPrintEnvDecl))
@ -11,3 +14,23 @@ makePPED namer suffixifier =
PrettyPrintEnvDecl
(PPE.makePPE namer PPE.dontSuffixify)
(PPE.makePPE namer suffixifier)
-- | Make a PPED suitable for names in a Unison file.
--
-- Such names have special suffixification rules: aliases may *not* be referred to by a common suffix. For example, if
-- a file contains
--
-- one.foo = 6
-- two.foo = 6
--
-- then the suffix `foo` will *not* be accepted (currently). So, this PPE uses the "suffixify by name" strategy.
makeFilePPED :: Names -> PrettyPrintEnvDecl
makeFilePPED names =
makePPED (PPE.namer names) (PPE.suffixifyByName names)
-- | Make a PPED suitable for names in the codebase. These names are hash qualified and suffixified by hash.
makeCodebasePPED :: Names -> PrettyPrintEnvDecl
makeCodebasePPED names =
makePPED
(PPE.hqNamer 10 names)
(PPE.suffixifyByHash names)

View File

@ -5,14 +5,12 @@
module Unison.Cli.UpdateUtils
( -- * Loading definitions
loadNamespaceDefinitions,
ConflictedName (..),
-- * Narrowing definitions
narrowDefns,
-- * Hydrating definitions
hydrateDefns,
hydrateDefnsRel,
-- * Rendering definitions
renderDefnsForUnisonFile,
@ -27,11 +25,9 @@ import Data.Foldable qualified as Foldable
import Data.List qualified as List
import Data.List.NonEmpty qualified as List.NonEmpty
import Data.Map.Strict qualified as Map
import Data.Semialign (alignWith)
import Data.Set qualified as Set
import Data.Set.NonEmpty (NESet)
import Data.Set.NonEmpty qualified as Set.NonEmpty
import Data.These (These (..))
import U.Codebase.Branch qualified as V2
import U.Codebase.Causal qualified
import U.Codebase.Reference (TermReferenceId, TypeReferenceId)
@ -61,15 +57,14 @@ import Unison.Type (Type)
import Unison.Typechecker qualified as Typechecker
import Unison.Util.BiMultimap (BiMultimap)
import Unison.Util.BiMultimap qualified as BiMultimap
import Unison.Util.Conflicted (Conflicted (..))
import Unison.Util.Defn (Defn (..))
import Unison.Util.Defns (Defns (..), DefnsF, DefnsF2)
import Unison.Util.Monoid qualified as Monoid
import Unison.Util.Nametree (Nametree (..), traverseNametreeWithName, unflattenNametree, unflattenNametrees)
import Unison.Util.Nametree (Nametree (..), traverseNametreeWithName, unflattenNametrees)
import Unison.Util.Pretty (ColorText, Pretty)
import Unison.Util.Pretty qualified as Pretty
import Unison.Util.Relation (Relation)
import Unison.Util.Relation qualified as Relation
import Unison.Util.Set qualified as Set
import Unison.Var (Var)
import Prelude hiding (unzip, zip, zipWith)
@ -85,7 +80,11 @@ loadNamespaceDefinitions ::
(Monad m) =>
(V2.Referent -> m Referent) ->
V2.Branch m ->
m (Either ConflictedName (Nametree (DefnsF (Map NameSegment) Referent TypeReference)))
m
( Either
(Defn (Conflicted Name Referent) (Conflicted Name TypeReference))
(Nametree (DefnsF (Map NameSegment) Referent TypeReference))
)
loadNamespaceDefinitions referent2to1 =
fmap assertNamespaceHasNoConflictedNames . go (Map.delete NameSegment.libSegment)
where
@ -102,25 +101,25 @@ loadNamespaceDefinitions referent2to1 =
go id child
pure Nametree {value = Defns {terms, types}, children}
data ConflictedName
= ConflictedName'Term !Name !(NESet Referent)
| ConflictedName'Type !Name !(NESet TypeReference)
-- | Assert that there are no unconflicted names in a namespace.
assertNamespaceHasNoConflictedNames ::
Nametree (DefnsF2 (Map NameSegment) NESet Referent TypeReference) ->
Either ConflictedName (Nametree (DefnsF (Map NameSegment) Referent TypeReference))
Either
(Defn (Conflicted Name Referent) (Conflicted Name TypeReference))
(Nametree (DefnsF (Map NameSegment) Referent TypeReference))
assertNamespaceHasNoConflictedNames =
traverseNametreeWithName \names defns -> do
traverseNametreeWithName \segments defns -> do
let toName segment =
Name.fromReverseSegments (segment List.NonEmpty.:| segments)
terms <-
defns.terms & Map.traverseWithKey \name ->
assertUnconflicted (ConflictedName'Term (Name.fromReverseSegments (name List.NonEmpty.:| names)))
defns.terms & Map.traverseWithKey \segment ->
assertUnconflicted (TermDefn . Conflicted (toName segment))
types <-
defns.types & Map.traverseWithKey \name ->
assertUnconflicted (ConflictedName'Type (Name.fromReverseSegments (name List.NonEmpty.:| names)))
defns.types & Map.traverseWithKey \segment ->
assertUnconflicted (TypeDefn . Conflicted (toName segment))
pure Defns {terms, types}
where
assertUnconflicted :: (NESet ref -> ConflictedName) -> NESet ref -> Either ConflictedName ref
assertUnconflicted :: (NESet ref -> x) -> NESet ref -> Either x ref
assertUnconflicted conflicted refs
| Set.NonEmpty.size refs == 1 = Right (Set.NonEmpty.findMin refs)
| otherwise = Left (conflicted refs)
@ -134,19 +133,28 @@ narrowDefns ::
forall term typ.
(Ord term, Ord typ) =>
DefnsF (Relation Name) term typ ->
Either (Defn Name Name) (Nametree (DefnsF (Map NameSegment) term typ))
Either
( Defn
(Conflicted Name term)
(Conflicted Name typ)
)
(Nametree (DefnsF (Map NameSegment) term typ))
narrowDefns =
fmap unflattenNametrees . bitraverse (mapLeft TermDefn . go) (mapLeft TypeDefn . go)
fmap unflattenNametrees
. bitraverse
(go (\name -> TermDefn . Conflicted name))
(go (\name -> TypeDefn . Conflicted name))
where
go :: (Ord ref) => Relation Name ref -> Either Name (Map Name ref)
go =
go :: forall ref x. (Ord ref) => (Name -> NESet ref -> x) -> Relation Name ref -> Either x (Map Name ref)
go conflicted =
Map.traverseWithKey unconflicted . Relation.domain
where
unconflicted :: Name -> Set ref -> Either Name ref
unconflicted name refs =
case Set.asSingleton refs of
Nothing -> Left name
Just ref -> Right ref
unconflicted :: Name -> Set ref -> Either x ref
unconflicted name refs0
| Set.NonEmpty.size refs == 1 = Right (Set.NonEmpty.findMin refs)
| otherwise = Left (conflicted name refs)
where
refs = Set.NonEmpty.unsafeFromSet refs0
------------------------------------------------------------------------------------------------------------------------
-- Hydrating definitions
@ -196,58 +204,6 @@ hydrateDefns_ getComponent defns modify =
defns2 =
BiMultimap.fromRange defns
-- | Like 'hydrateDefns', but when you have a relation (i.e. names can be conflicted). Maybe this code should be deleted
-- in favor of just asserting that names can't be conflicted before doing something (since it's easy to resolve: just
-- rename one). But, for now, this exists.
hydrateDefnsRel ::
forall m name term typ.
(Monad m, Ord name, Ord term, Ord typ) =>
(Hash -> m [term]) ->
(Hash -> m [typ]) ->
DefnsF (Relation name) TermReferenceId TypeReferenceId ->
m (DefnsF (Relation name) term (TypeReferenceId, typ))
hydrateDefnsRel getTermComponent getTypeComponent = do
bitraverse hydrateTerms hydrateTypes
where
hydrateTerms :: Relation name TermReferenceId -> m (Relation name term)
hydrateTerms terms =
hydrateDefnsRel_ getTermComponent terms \_ _ -> id
hydrateTypes :: Relation name TypeReferenceId -> m (Relation name (TypeReferenceId, typ))
hydrateTypes types =
hydrateDefnsRel_ getTypeComponent types \_ -> (,)
hydrateDefnsRel_ ::
forall a b name m.
(Ord b, Monad m, Ord name) =>
(Hash -> m [a]) ->
Relation name Reference.Id ->
(name -> Reference.Id -> a -> b) ->
m (Relation name b)
hydrateDefnsRel_ getComponent defns modify =
let hashes :: [Hash]
hashes =
defns
& Relation.toList
& List.foldl' (\acc (_, ref) -> Set.insert (Reference.idToHash ref) acc) Set.empty
& Set.toList
in hashes & Monoid.foldMapM \hash -> do
component <- getComponent hash
pure
( List.foldl'
f
Relation.empty
(Reference.componentFor hash component)
)
where
f :: Relation name b -> (Reference.Id, a) -> Relation name b
f acc (ref, x) =
List.foldl' (g ref x) acc (Set.toList (Relation.lookupRan ref defns))
g :: Reference.Id -> a -> Relation name b -> name -> Relation name b
g ref x acc2 name =
Relation.insert name (modify name ref x) acc2
------------------------------------------------------------------------------------------------------------------------
-- Rendering definitions

View File

@ -44,7 +44,7 @@ import Unison.Cli.Monad (Cli)
import Unison.Cli.Monad qualified as Cli
import Unison.Cli.MonadUtils qualified as Cli
import Unison.Cli.ProjectUtils qualified as ProjectUtils
import Unison.Cli.UpdateUtils (hydrateDefns, renderDefnsForUnisonFile, ConflictedName (..), loadNamespaceDefinitions)
import Unison.Cli.UpdateUtils (hydrateDefns, loadNamespaceDefinitions, renderDefnsForUnisonFile)
import Unison.Codebase (Codebase)
import Unison.Codebase qualified as Codebase
import Unison.Codebase.Branch (Branch0)
@ -70,7 +70,7 @@ import Unison.Debug qualified as Debug
import Unison.Hash qualified as Hash
import Unison.Merge.CombineDiffs (CombinedDiffOp (..), combineDiffs)
import Unison.Merge.Database (MergeDatabase (..), makeMergeDatabase, referent2to1)
import Unison.Merge.DeclCoherencyCheck (IncoherentDeclReason (..), checkDeclCoherency, lenientCheckDeclCoherency)
import Unison.Merge.DeclCoherencyCheck (checkDeclCoherency, lenientCheckDeclCoherency)
import Unison.Merge.DeclNameLookup (DeclNameLookup (..), expectConstructorNames)
import Unison.Merge.Diff qualified as Merge
import Unison.Merge.DiffOp (DiffOp (..))
@ -228,10 +228,8 @@ doMerge info = do
(defns3, declNameLookups, lcaDeclNameLookup) <- do
let emptyNametree = Nametree {value = Defns Map.empty Map.empty, children = Map.empty}
let loadDefns branch =
Cli.runTransaction (loadNamespaceDefinitions (referent2to1 db) branch) & onLeftM \conflictedName ->
done case conflictedName of
ConflictedName'Term name refs -> Output.MergeConflictedTermName name refs
ConflictedName'Type name refs -> Output.MergeConflictedTypeName name refs
Cli.runTransaction (loadNamespaceDefinitions (referent2to1 db) branch)
& onLeftM (done . Output.ConflictedDefn "merge")
let load = \case
Nothing -> pure (emptyNametree, DeclNameLookup Map.empty Map.empty)
Just (who, branch) -> do
@ -244,14 +242,7 @@ doMerge info = do
Reference.toId
defns
)
& onLeftM \err ->
done case err of
IncoherentDeclReason'ConstructorAlias typeName conName1 conName2 ->
Output.MergeConstructorAlias who typeName conName1 conName2
IncoherentDeclReason'MissingConstructorName name -> Output.MergeMissingConstructorName who name
IncoherentDeclReason'NestedDeclAlias shorterName longerName ->
Output.MergeNestedDeclAlias who shorterName longerName
IncoherentDeclReason'StrayConstructor _typeRef name -> Output.MergeStrayConstructor who name
& onLeftM (done . Output.IncoherentDeclDuringMerge who)
pure (defns, declNameLookup)
(aliceDefns0, aliceDeclNameLookup) <- load (Just (mergeTarget, branches.alice))

View File

@ -4,7 +4,6 @@ module Unison.Codebase.Editor.HandleInput.Update2
-- * Misc helpers to be organized later
addDefinitionsToUnisonFile,
makeUnisonFile,
findCtorNames,
findCtorNamesMaybe,
forwardCtorNames,
@ -15,7 +14,6 @@ module Unison.Codebase.Editor.HandleInput.Update2
typecheckedUnisonFileToBranchAdds,
getNamespaceDependentsOf,
getNamespaceDependentsOf2,
makeComplicatedPPE,
)
where
@ -28,24 +26,22 @@ import Data.List.NonEmpty qualified as NonEmpty
import Data.List.NonEmpty.Extra ((|>))
import Data.Map qualified as Map
import Data.Maybe (fromJust)
import Data.Semialign (alignWith)
import Data.Set qualified as Set
import Data.Text qualified as Text
import Data.Text.Lazy qualified as Lazy.Text
import Data.These (These (..))
import Text.Pretty.Simple (pShow)
import U.Codebase.Reference (Reference, TermReferenceId)
import U.Codebase.Reference qualified as Reference
import U.Codebase.Sqlite.Operations qualified as Operations
import U.Codebase.Sqlite.Operations qualified as Ops
import Unison.Builtin.Decls qualified as Decls
import Unison.Cli.Monad (Cli)
import Unison.Cli.Monad (Cli, Env (..))
import Unison.Cli.Monad qualified as Cli
import Unison.Cli.MonadUtils qualified as Cli
import Unison.Cli.Pretty qualified as Pretty
import Unison.Cli.TypeCheck (computeTypecheckingEnvironment)
import Unison.Cli.UniqueTypeGuidLookup qualified as Cli
import Unison.Cli.UpdateUtils (hydrateDefns, hydrateDefnsRel, narrowDefns, renderDefnsForUnisonFile)
import Unison.Cli.UpdateUtils (hydrateDefns, narrowDefns, renderDefnsForUnisonFile)
import Unison.Codebase qualified as Codebase
import Unison.Codebase.Branch (Branch0)
import Unison.Codebase.Branch qualified as Branch
@ -67,13 +63,13 @@ import Unison.Debug qualified as Debug
import Unison.FileParsers qualified as FileParsers
import Unison.Hash (Hash)
import Unison.Merge.DeclCoherencyCheck (checkDeclCoherency)
import Unison.Merge.DeclNameLookup (DeclNameLookup (..))
import Unison.Name (Name)
import Unison.Name qualified as Name
import Unison.Name.Forward (ForwardName (..))
import Unison.Name.Forward qualified as ForwardName
import Unison.NameSegment qualified as NameSegment
import Unison.NameSegment.Internal (NameSegment (NameSegment))
import Unison.Names (Names (Names))
import Unison.Names (Names)
import Unison.Names qualified as Names
import Unison.Parser.Ann (Ann)
import Unison.Parser.Ann qualified as Ann
@ -83,7 +79,7 @@ import Unison.PrettyPrintEnv.Names qualified as PPE
import Unison.PrettyPrintEnvDecl (PrettyPrintEnvDecl)
import Unison.PrettyPrintEnvDecl qualified as PPED
import Unison.PrettyPrintEnvDecl.Names qualified as PPED
import Unison.Reference (Reference' (..), TypeReference, TypeReferenceId)
import Unison.Reference (TypeReference, TypeReferenceId)
import Unison.Reference qualified as Reference (fromId)
import Unison.Referent (Referent)
import Unison.Referent qualified as Referent
@ -103,7 +99,7 @@ import Unison.Util.BiMultimap (BiMultimap)
import Unison.Util.BiMultimap qualified as BiMultimap
import Unison.Util.Defns (Defns (..), DefnsF, defnsAreEmpty)
import Unison.Util.Monoid qualified as Monoid
import Unison.Util.Nametree (Nametree, unflattenNametree, flattenNametrees)
import Unison.Util.Nametree (flattenNametrees)
import Unison.Util.Pretty (ColorText, Pretty)
import Unison.Util.Pretty qualified as Pretty
import Unison.Util.Relation (Relation)
@ -114,7 +110,7 @@ import Unison.WatchKind qualified as WK
handleUpdate2 :: Cli ()
handleUpdate2 = do
Cli.Env {codebase, writeSource} <- ask
env <- ask
tuf <- Cli.expectLatestTypecheckedFile
let termAndDeclNames = getTermAndDeclNames tuf
pp <- Cli.getCurrentProjectPath
@ -122,13 +118,11 @@ handleUpdate2 = do
let currentBranch0ExcludingLibdeps = Branch.deleteLibdeps currentBranch0
let namesIncludingLibdeps = Branch.toNames currentBranch0
let namesExcludingLibdeps = Branch.toNames currentBranch0ExcludingLibdeps
let ctorNames = forwardCtorNames namesExcludingLibdeps
-- Assert that the namespace doesn't have any conflicted names
defns <-
narrowDefns
(Branch.deepDefns currentBranch0ExcludingLibdeps)
& onLeft \conflictedName -> wundefined
narrowDefns (Branch.deepDefns currentBranch0ExcludingLibdeps)
& onLeft (Cli.returnEarly . Output.ConflictedDefn "update")
-- Assert that the namespace doesn't have any incoherent decls
declNameLookup <-
@ -139,55 +133,54 @@ handleUpdate2 = do
Reference.toId
defns
)
& onLeftM \err -> wundefined
let defns1 = flattenNametrees defns
& onLeftM (Cli.returnEarly . Output.IncoherentDeclDuringUpdate)
Cli.respond Output.UpdateLookingForDependents
dependents0 <-
(dependents, hydratedDependents) <-
Cli.runTransaction do
getNamespaceDependentsOf2
defns1
(getExistingReferencesNamed termAndDeclNames namesExcludingLibdeps)
-- Get all dependents of things being updated
dependents0 <-
getNamespaceDependentsOf2
(flattenNametrees defns)
(getExistingReferencesNamed termAndDeclNames namesExcludingLibdeps)
-- Throw away the dependents that are shadowed by the file itself
let dependents1 :: DefnsF (Map Name) TermReferenceId TypeReferenceId
dependents1 =
bimap
(`Map.withoutKeys` (Set.map Name.unsafeParseVar (UF.termNamespaceBindings tuf)))
(`Map.withoutKeys` (Set.map Name.unsafeParseVar (UF.typeNamespaceBindings tuf)))
dependents0
-- Throw away the dependents that are shadowed by the file itself
let dependents1 :: DefnsF (Map Name) TermReferenceId TypeReferenceId
dependents1 =
bimap
(`Map.withoutKeys` (Set.map Name.unsafeParseVar (UF.termNamespaceBindings tuf)))
(`Map.withoutKeys` (Set.map Name.unsafeParseVar (UF.typeNamespaceBindings tuf)))
dependents0
-- Hydrate the dependents for rendering
hydratedDependents <-
hydrateDefns
(Codebase.unsafeGetTermComponent env.codebase)
Operations.expectDeclComponent
dependents1
pure (dependents1, hydratedDependents)
secondTuf <- do
case defnsAreEmpty dependents1 of
case defnsAreEmpty dependents of
-- If there are no dependents of the updates, then just use the already-typechecked file.
True -> pure tuf
False -> do
hydratedDependents <-
Cli.runTransaction do
hydrateDefns
(Codebase.unsafeGetTermComponent codebase)
Operations.expectDeclComponent
dependents1
let ppe = makeComplicatedPPE2 10 namesIncludingLibdeps (UF.typecheckedToNames tuf) dependents1
let renderedDependents :: DefnsF (Map Name) (Pretty ColorText) (Pretty ColorText)
renderedDependents =
renderDefnsForUnisonFile declNameLookup ppe hydratedDependents
Cli.respond Output.UpdateStartTypechecking
let prettyUnisonFile =
makePrettyUnisonFile (Pretty.prettyUnisonFile ppe (UF.discardTypes tuf)) renderedDependents
Cli.respond Output.UpdateStartTypechecking
let ppe = makePPE 10 namesIncludingLibdeps (UF.typecheckedToNames tuf) dependents
in makePrettyUnisonFile
(Pretty.prettyUnisonFile ppe (UF.discardTypes tuf))
(renderDefnsForUnisonFile declNameLookup ppe hydratedDependents)
parsingEnv <- makeParsingEnv pp namesIncludingLibdeps
secondTuf <-
prettyParseTypecheck2 prettyUnisonFile parsingEnv & onLeftM \prettyUf -> do
scratchFilePath <- fst <$> Cli.expectLatestFile
liftIO $ writeSource (Text.pack scratchFilePath) (Text.pack $ Pretty.toPlain 80 prettyUf)
liftIO $ env.writeSource (Text.pack scratchFilePath) (Text.pack $ Pretty.toPlain 80 prettyUf)
Cli.returnEarly Output.UpdateTypecheckingFailure
Cli.respond Output.UpdateTypecheckingSuccess
@ -201,7 +194,7 @@ handleUpdate2 = do
Codebase.addDefsToCodebase env.codebase secondTuf
typecheckedUnisonFileToBranchUpdates
abort
(findCtorNamesMaybe Output.UOUUpdate namesExcludingLibdeps ctorNames Nothing)
(\typeName -> Right (Map.lookup typeName declNameLookup.declToConstructors))
secondTuf
Cli.stepAt "update" (path, Branch.batchUpdates branchUpdates)
@ -219,7 +212,7 @@ makePrettyUnisonFile originalFile dependents =
<> Pretty.newline
<> ( dependents
& inAlphabeticalOrder
& let f = foldMap (<> "\n") in bifoldMap f f
& let f = foldMap (\defn -> defn <> Pretty.newline <> Pretty.newline) in bifoldMap f f
)
where
inAlphabeticalOrder :: DefnsF (Map Name) a b -> DefnsF [] a b
@ -308,7 +301,10 @@ typecheckedUnisonFileToBranchUpdates abort getConstructors tuf = do
-- some decls will be deleted, we want to delete their
-- constructors as well
deleteConstructorActions <-
(maybe [] (map (BranchUtil.makeAnnihilateTermName . Path.splitFromName)) <$> getConstructors (Name.unsafeParseVar symbol)) & onLeft abort
( maybe [] (map (BranchUtil.makeAnnihilateTermName . Path.splitFromName))
<$> getConstructors (Name.unsafeParseVar symbol)
)
& onLeft abort
let deleteTypeAction = BranchUtil.makeAnnihilateTypeName split
split = splitVar symbol
insertTypeAction = BranchUtil.makeAddTypeName split (Reference.fromId typeRefId)
@ -635,72 +631,16 @@ getNamespaceDependentsOf2 defns dependencies = do
-- However, the following file will not fail to parse, if `one.foo` and `two.foo` are aliases in the codebase:
--
-- hey = foo + foo
makeComplicatedPPE ::
Int ->
Names ->
Names ->
DefnsF (Relation Name) TermReferenceId TypeReferenceId ->
PrettyPrintEnvDecl
makeComplicatedPPE hashLen names initialFileNames dependents =
primaryPPE `PPED.addFallback` secondaryPPE
where
primaryPPE =
PPED.makePPED (PPE.namer namesInTheFile) (PPE.suffixifyByName namesInTheFile)
secondaryPPE =
PPED.makePPED
(PPE.hqNamer hashLen names)
-- We don't want to over-suffixify for a reference in the namespace. For example, say we have "foo.bar" in the
-- namespace and "oink.bar" in the file. "bar" may be a unique suffix among the namespace names, but would be
-- ambiguous in the context of namespace + file names.
--
-- So, we use `unionLeftName`, which starts with the LHS names (the namespace), and adds to it names from the
-- RHS (the initial file names, i.e. what was originally saved) that don't already exist in the LHS.
(PPE.suffixifyByHash (Names.unionLeftName names initialFileNames))
namesInTheFile =
initialFileNames <> dependentsNames
dependentsNames =
Names
{ terms = Relation.mapRan Referent.fromTermReferenceId dependents.terms,
types = Relation.mapRan Reference.fromId dependents.types
}
-- The big picture behind PPE building, though there are many details:
--
-- * We are updating old references to new references by rendering old references as names that are then parsed
-- back to resolve to new references (the world's weirdest implementation of AST substitution).
--
-- * We have to render names that refer to definitions in the file with a different suffixification strategy
-- (namely, "suffixify by name") than names that refer to things in the codebase.
--
-- This is because you *may* refer to aliases that share a suffix by that suffix for definitions in the
-- codebase, but not in the file.
--
-- For example, the following file will fail to parse:
--
-- one.foo = 10
-- two.foo = 10
-- hey = foo + foo -- "Which foo do you mean? There are two."
--
-- However, the following file will not fail to parse, if `one.foo` and `two.foo` are aliases in the codebase:
--
-- hey = foo + foo
makeComplicatedPPE2 ::
makePPE ::
Int ->
Names ->
Names ->
DefnsF (Map Name) TermReferenceId TypeReferenceId ->
PrettyPrintEnvDecl
makeComplicatedPPE2 hashLen names initialFileNames dependents =
primaryPPE `PPED.addFallback` secondaryPPE
where
primaryPPE =
PPED.makePPED (PPE.namer namesInTheFile) (PPE.suffixifyByName namesInTheFile)
secondaryPPE =
PPED.makePPED
makePPE hashLen names initialFileNames dependents =
PPED.addFallback
(PPED.makeFilePPED (initialFileNames <> Names.fromUnconflictedReferenceIds dependents))
( PPED.makePPED
(PPE.hqNamer hashLen names)
-- We don't want to over-suffixify for a reference in the namespace. For example, say we have "foo.bar" in the
-- namespace and "oink.bar" in the file. "bar" may be a unique suffix among the namespace names, but would be
@ -709,12 +649,4 @@ makeComplicatedPPE2 hashLen names initialFileNames dependents =
-- So, we use `unionLeftName`, which starts with the LHS names (the namespace), and adds to it names from the
-- RHS (the initial file names, i.e. what was originally saved) that don't already exist in the LHS.
(PPE.suffixifyByHash (Names.unionLeftName names initialFileNames))
namesInTheFile =
initialFileNames <> dependentsNames
dependentsNames =
Names
{ terms = Relation.fromMap (Map.map Referent.fromTermReferenceId dependents.terms),
types = Relation.fromMap (Map.map Reference.fromId dependents.types)
}
)

View File

@ -27,7 +27,6 @@ import Unison.Codebase.Editor.HandleInput.Update2
findCtorNamesMaybe,
forwardCtorNames,
getNamespaceDependentsOf,
makeComplicatedPPE,
makeParsingEnv,
prettyParseTypecheck,
typecheckedUnisonFileToBranchUpdates,
@ -47,6 +46,7 @@ import Unison.PrettyPrintEnv qualified as PPE
import Unison.PrettyPrintEnv.Names qualified as PPE
import Unison.PrettyPrintEnvDecl (PrettyPrintEnvDecl (..))
import Unison.PrettyPrintEnvDecl qualified as PPED (addFallback)
import Unison.PrettyPrintEnvDecl.Names qualified as PPED (makeCodebasePPED, makeFilePPED)
import Unison.Project (ProjectBranchName)
import Unison.Reference (TermReference, TypeReference)
import Unison.Referent (Referent)
@ -138,7 +138,6 @@ handleUpgrade oldName newName = do
(findCtorNames Output.UOUUpgrade currentLocalNames currentLocalConstructorNames)
dependents
UnisonFile.emptyUnisonFile
hashLength <- Codebase.hashLength
pure
( unisonFile,
makeOldDepPPE
@ -148,7 +147,8 @@ handleUpgrade oldName newName = do
(Branch.toNames oldNamespace)
(Branch.toNames oldLocalNamespace)
(Branch.toNames newLocalNamespace)
`PPED.addFallback` makeComplicatedPPE hashLength currentDeepNamesSansOld mempty dependents
`PPED.addFallback` PPED.makeFilePPED (Names.fromReferenceIds dependents)
`PPED.addFallback` PPED.makeCodebasePPED currentDeepNamesSansOld
)
pp@(PP.ProjectPath project projectBranch _path) <- Cli.getCurrentProjectPath

View File

@ -57,7 +57,7 @@ import Unison.Hash (Hash)
import Unison.HashQualified qualified as HQ
import Unison.HashQualifiedPrime qualified as HQ'
import Unison.LabeledDependency (LabeledDependency)
import Unison.Merge.DeclCoherencyCheck (IncoherentDeclReasons (..))
import Unison.Merge.DeclCoherencyCheck (IncoherentDeclReason, IncoherentDeclReasons (..))
import Unison.Name (Name)
import Unison.NameSegment (NameSegment)
import Unison.Names (Names)
@ -84,6 +84,8 @@ import Unison.Term (Term)
import Unison.Type (Type)
import Unison.Typechecker.Context qualified as Context
import Unison.UnisonFile qualified as UF
import Unison.Util.Conflicted (Conflicted)
import Unison.Util.Defn (Defn)
import Unison.Util.Defns (DefnsF, defnsAreEmpty)
import Unison.Util.Pretty qualified as P
import Unison.Util.Relation (Relation)
@ -199,15 +201,15 @@ data Output
| -- | Function found, but has improper type
-- Note: the constructor name is misleading here; we weren't necessarily looking for a "main".
BadMainFunction
-- | what we were trying to do (e.g. "run", "io.test")
Text
-- ^ what we were trying to do (e.g. "run", "io.test")
-- | name of function
(HQ.HashQualified Name)
-- ^ name of function
-- | bad type of function
(Type Symbol Ann)
-- ^ bad type of function
PPE.PrettyPrintEnv
-- | acceptable type(s) of function
[Type Symbol Ann]
-- ^ acceptable type(s) of function
| BranchEmpty WhichBranchEmpty
| LoadPullRequest (ReadRemoteNamespace Void) (ReadRemoteNamespace Void) Path' Path' Path' Path'
| CreatedNewBranch Path.Absolute
@ -244,12 +246,12 @@ data Output
-- for terms. This additional info is used to provide an enhanced
-- error message.
SearchTermsNotFoundDetailed
-- | @True@ if we are searching for a term, @False@ if we are searching for a type
Bool
-- ^ @True@ if we are searching for a term, @False@ if we are searching for a type
-- | Misses (search terms that returned no hits for terms or types)
[HQ.HashQualified Name]
-- ^ Misses (search terms that returned no hits for terms or types)
-- | Hits for types if we are searching for terms or terms if we are searching for types
[HQ.HashQualified Name]
-- ^ Hits for types if we are searching for terms or terms if we are searching for types
| -- ask confirmation before deleting the last branch that contains some defns
-- `Path` is one of the paths the user has requested to delete, and is paired
-- with whatever named definitions would not have any remaining names if
@ -392,8 +394,8 @@ data Output
| CalculatingDiff
| -- | The `local` in a `clone remote local` is ambiguous
AmbiguousCloneLocal
-- | Treating `local` as a project. We may know the branch name, if it was provided in `remote`.
(ProjectAndBranch ProjectName ProjectBranchName)
-- ^ Treating `local` as a project. We may know the branch name, if it was provided in `remote`.
(ProjectAndBranch ProjectName ProjectBranchName)
| -- | The `remote` in a `clone remote local` is ambiguous
AmbiguousCloneRemote ProjectName (ProjectAndBranch ProjectName ProjectBranchName)
@ -419,20 +421,17 @@ data Output
| MergeSuccess !MergeSourceAndTarget
| MergeSuccessFastForward !MergeSourceAndTarget
| MergeConflictedAliases !MergeSourceOrTarget !Name !Name
| MergeConflictedTermName !Name !(NESet Referent)
| MergeConflictedTypeName !Name !(NESet TypeReference)
| MergeConflictInvolvingBuiltin !Name
| MergeConstructorAlias !MergeSourceOrTarget !Name !Name !Name
| MergeDefnsInLib !MergeSourceOrTarget
| MergeMissingConstructorName !MergeSourceOrTarget !Name
| MergeNestedDeclAlias !MergeSourceOrTarget !Name !Name
| MergeStrayConstructor !MergeSourceOrTarget !Name
| InstalledLibdep !(ProjectAndBranch ProjectName ProjectBranchName) !NameSegment
| NoUpgradeInProgress
| UseLibInstallNotPull !(ProjectAndBranch ProjectName ProjectBranchName)
| PullIntoMissingBranch !(ReadRemoteNamespace Share.RemoteProjectBranch) !(ProjectAndBranch (Maybe ProjectName) ProjectBranchName)
| NoMergeInProgress
| Output'DebugSynhashTerm !TermReference !Hash !Text
| ConflictedDefn !Text {- what operation? -} !(Defn (Conflicted Name Referent) (Conflicted Name TypeReference))
| IncoherentDeclDuringMerge !MergeSourceOrTarget !IncoherentDeclReason
| IncoherentDeclDuringUpdate !IncoherentDeclReason
data MoreEntriesThanShown = MoreEntriesThanShown | AllEntriesShown
deriving (Eq, Show)
@ -658,20 +657,17 @@ isFailure o = case o of
MergeSuccess {} -> False
MergeSuccessFastForward {} -> False
MergeConflictedAliases {} -> True
MergeConflictedTermName {} -> True
MergeConflictedTypeName {} -> True
MergeConflictInvolvingBuiltin {} -> True
MergeConstructorAlias {} -> True
MergeDefnsInLib {} -> True
MergeMissingConstructorName {} -> True
MergeNestedDeclAlias {} -> True
MergeStrayConstructor {} -> True
InstalledLibdep {} -> False
NoUpgradeInProgress {} -> True
UseLibInstallNotPull {} -> False
PullIntoMissingBranch {} -> True
NoMergeInProgress {} -> True
Output'DebugSynhashTerm {} -> False
ConflictedDefn {} -> True
IncoherentDeclDuringMerge {} -> True
IncoherentDeclDuringUpdate {} -> True
isNumberedFailure :: NumberedOutput -> Bool
isNumberedFailure = \case

View File

@ -85,7 +85,7 @@ import Unison.Hash32 (Hash32)
import Unison.HashQualified qualified as HQ
import Unison.HashQualifiedPrime qualified as HQ'
import Unison.LabeledDependency as LD
import Unison.Merge.DeclCoherencyCheck (IncoherentDeclReasons (..))
import Unison.Merge.DeclCoherencyCheck (IncoherentDeclReason (..), IncoherentDeclReasons (..))
import Unison.Name (Name)
import Unison.Name qualified as Name
import Unison.NameSegment qualified as NameSegment
@ -141,6 +141,8 @@ import Unison.Term (Term)
import Unison.Term qualified as Term
import Unison.Type (Type)
import Unison.UnisonFile qualified as UF
import Unison.Util.Conflicted (Conflicted (..))
import Unison.Util.Defn (Defn (..))
import Unison.Util.Defns (Defns (..))
import Unison.Util.List qualified as List
import Unison.Util.Monoid (intercalateMap)
@ -1384,12 +1386,6 @@ notifyUser dir = \case
<> P.newline
<> P.newline
<> P.wrap "and then try merging again."
MergeConflictedTermName name _refs ->
pure . P.wrap $
"The term name" <> prettyName name <> "is ambiguous. Please resolve the ambiguity before merging."
MergeConflictedTypeName name _refs ->
pure . P.wrap $
"The type name" <> prettyName name <> "is ambiguous. Please resolve the ambiguity before merging."
MergeConflictInvolvingBuiltin name ->
pure . P.lines $
[ P.wrap "Sorry, I wasn't able to perform the merge:",
@ -1406,22 +1402,6 @@ notifyUser dir = \case
<> "the same on both branches, or making neither of them a builtin, and then try the merge again."
)
]
-- Note [ConstructorAliasMessage] If you change this, also change the other similar one
MergeConstructorAlias aliceOrBob typeName conName1 conName2 ->
pure . P.lines $
[ P.wrap "Sorry, I wasn't able to perform the merge:",
"",
P.wrap $
"On"
<> P.group (prettyMergeSourceOrTarget aliceOrBob <> ",")
<> "the type"
<> prettyName typeName
<> "has a constructor with multiple names, and I can't perform a merge in this situation:",
"",
P.indentN 2 (P.bulleted [prettyName conName1, prettyName conName2]),
"",
P.wrap "Please delete all but one name for each constructor, and then try merging again."
]
-- Note [DefnsInLibMessage] If you change this, also change the other similar one
MergeDefnsInLib aliceOrBob ->
pure . P.lines $
@ -1435,54 +1415,6 @@ notifyUser dir = \case
"",
P.wrap "Please move or remove it and then try merging again."
]
-- Note [MissingConstructorNameMessage] If you change this, also change the other similar one
MergeMissingConstructorName aliceOrBob name ->
pure . P.lines $
[ P.wrap "Sorry, I wasn't able to perform the merge:",
"",
P.wrap $
"On"
<> P.group (prettyMergeSourceOrTarget aliceOrBob <> ",")
<> "the type"
<> prettyName name
<> "has some constructors with missing names, and I can't perform a merge in this situation.",
"",
P.wrap $
"You can use"
<> IP.makeExample IP.view [prettyName name]
<> "and"
<> IP.makeExample IP.aliasTerm ["<hash>", prettyName name <> ".<ConstructorName>"]
<> "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 ->
pure . P.wrap $
"On"
<> P.group (prettyMergeSourceOrTarget aliceOrBob <> ",")
<> "the type"
<> prettyName longerName
<> "is an alias of"
<> P.group (prettyName shorterName <> ".")
<> "I'm not able to perform a merge when a type exists nested under an alias of itself. Please separate them or"
<> "delete one copy, and then try merging again."
-- Note [StrayConstructorMessage] If you change this, also change the other similar one
MergeStrayConstructor aliceOrBob name ->
pure . P.lines $
[ P.wrap $
"Sorry, I wasn't able to perform the merge, because I need all constructor names to be nested somewhere"
<> "beneath the corresponding type name.",
"",
P.wrap $
"On"
<> P.group (prettyMergeSourceOrTarget aliceOrBob <> ",")
<> "the constructor"
<> prettyName name
<> "is not nested beneath the corresponding type name. Please either use"
<> IP.makeExample' IP.moveAll
<> "to move it, or if it's an extra copy, you can simply"
<> IP.makeExample' IP.delete
<> "it. Then try the merge again."
]
PreviewMergeAlreadyUpToDate src dest ->
pure . P.callout "😶" $
P.wrap $
@ -2161,6 +2093,139 @@ notifyUser dir = \case
<> P.newline
<> "Synhash tokens: "
<> P.text filename
ConflictedDefn operation defn ->
pure . P.wrap $
( case defn of
TermDefn (Conflicted name _refs) -> "The term name" <> prettyName name <> "is ambiguous."
TypeDefn (Conflicted name _refs) -> "The type name" <> prettyName name <> "is ambiguous."
)
<> "Please resolve the ambiguity, then try to"
<> P.text operation
<> "again."
IncoherentDeclDuringMerge aliceOrBob reason ->
case reason of
-- Note [ConstructorAliasMessage] If you change this, also change the other similar ones
IncoherentDeclReason'ConstructorAlias typeName conName1 conName2 ->
pure . P.lines $
[ P.wrap "Sorry, I wasn't able to perform the merge:",
"",
P.wrap $
"On"
<> P.group (prettyMergeSourceOrTarget aliceOrBob <> ",")
<> "the type"
<> prettyName typeName
<> "has a constructor with multiple names, and I can't perform a merge in this situation:",
"",
P.indentN 2 (P.bulleted [prettyName conName1, prettyName conName2]),
"",
P.wrap "Please delete all but one name for each constructor, and then try merging again."
]
-- Note [MissingConstructorNameMessage] If you change this, also change the other similar ones
IncoherentDeclReason'MissingConstructorName name ->
pure . P.lines $
[ P.wrap "Sorry, I wasn't able to perform the merge:",
"",
P.wrap $
"On"
<> P.group (prettyMergeSourceOrTarget aliceOrBob <> ",")
<> "the type"
<> prettyName name
<> "has some constructors with missing names, and I can't perform a merge in this situation.",
"",
P.wrap $
"You can use"
<> IP.makeExample IP.view [prettyName name]
<> "and"
<> IP.makeExample IP.aliasTerm ["<hash>", prettyName name <> ".<ConstructorName>"]
<> "to give names to each unnamed constructor, and then try the merge again."
]
-- Note [NestedDeclAliasMessage] If you change this, also change the other similar ones
IncoherentDeclReason'NestedDeclAlias shorterName longerName ->
pure . P.wrap $
"On"
<> P.group (prettyMergeSourceOrTarget aliceOrBob <> ",")
<> "the type"
<> prettyName longerName
<> "is an alias of"
<> P.group (prettyName shorterName <> ".")
<> "I'm not able to perform a merge when a type exists nested under an alias of itself. Please separate them or"
<> "delete one copy, and then try merging again."
-- Note [StrayConstructorMessage] If you change this, also change the other similar ones
IncoherentDeclReason'StrayConstructor _typeRef name ->
pure . P.lines $
[ P.wrap $
"Sorry, I wasn't able to perform the merge, because I need all constructor names to be nested somewhere"
<> "beneath the corresponding type name.",
"",
P.wrap $
"On"
<> P.group (prettyMergeSourceOrTarget aliceOrBob <> ",")
<> "the constructor"
<> prettyName name
<> "is not nested beneath the corresponding type name. Please either use"
<> IP.makeExample' IP.moveAll
<> "to move it, or if it's an extra copy, you can simply"
<> IP.makeExample' IP.delete
<> "it. Then try the merge again."
]
IncoherentDeclDuringUpdate reason ->
case reason of
-- Note [ConstructorAliasMessage] If you change this, also change the other similar ones
IncoherentDeclReason'ConstructorAlias typeName conName1 conName2 ->
pure . P.lines $
[ P.wrap "Sorry, I wasn't able to perform the update:",
"",
P.wrap $
"The type"
<> prettyName typeName
<> "has a constructor with multiple names, and I can't perform an update in this situation:",
"",
P.indentN 2 (P.bulleted [prettyName conName1, prettyName conName2]),
"",
P.wrap "Please delete all but one name for each constructor, and then try updating again."
]
-- Note [MissingConstructorNameMessage] If you change this, also change the other similar ones
IncoherentDeclReason'MissingConstructorName name ->
pure . P.lines $
[ P.wrap "Sorry, I wasn't able to perform the update:",
"",
P.wrap $
"The type"
<> prettyName name
<> "has some constructors with missing names, and I can't perform an update in this situation.",
"",
P.wrap $
"You can use"
<> IP.makeExample IP.view [prettyName name]
<> "and"
<> IP.makeExample IP.aliasTerm ["<hash>", prettyName name <> ".<ConstructorName>"]
<> "to give names to each unnamed constructor, and then try the update again."
]
-- Note [NestedDeclAliasMessage] If you change this, also change the other similar ones
IncoherentDeclReason'NestedDeclAlias shorterName longerName ->
pure . P.wrap $
"The type"
<> prettyName longerName
<> "is an alias of"
<> P.group (prettyName shorterName <> ".")
<> "I'm not able to perform an update when a type exists nested under an alias of itself. Please separate"
<> "them or delete one copy, and then try updating again."
-- Note [StrayConstructorMessage] If you change this, also change the other similar ones
IncoherentDeclReason'StrayConstructor _typeRef name ->
pure . P.lines $
[ P.wrap $
"Sorry, I wasn't able to perform the update, because I need all constructor names to be nested somewhere"
<> "beneath the corresponding type name.",
"",
P.wrap $
"The constructor"
<> prettyName name
<> "is not nested beneath the corresponding type name. Please either use"
<> IP.makeExample' IP.moveAll
<> "to move it, or if it's an extra copy, you can simply"
<> IP.makeExample' IP.delete
<> "it. Then try the update again."
]
prettyShareError :: ShareError -> Pretty
prettyShareError =
@ -2701,7 +2766,7 @@ handleTodoOutput todo
things
& map
( \(typeName, prettyCon1, prettyCon2) ->
-- Note [ConstructorAliasMessage] If you change this, also change the other similar one
-- Note [ConstructorAliasMessage] If you change this, also change the other similar ones
P.wrap ("The type" <> prettyName typeName <> "has a constructor with multiple names.")
<> P.newline
<> P.newline
@ -2720,7 +2785,7 @@ handleTodoOutput todo
for types0 \typ -> do
n <- addNumberedArg (SA.Name typ)
pure (n, typ)
-- Note [MissingConstructorNameMessage] If you change this, also change the other similar one
-- Note [MissingConstructorNameMessage] If you change this, also change the other similar ones
pure $
P.wrap
"These types have some constructors with missing names."
@ -2753,7 +2818,7 @@ handleTodoOutput todo
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
-- Note [NestedDeclAliasMessage] If you change this, also change the other similar ones
pure $
aliases1
& map
@ -2775,7 +2840,7 @@ handleTodoOutput todo
nums <-
for constructors \(_typeRef, constructor) -> do
addNumberedArg (SA.Name constructor)
-- Note [StrayConstructorMessage] If you change this, also change the other similar one
-- Note [StrayConstructorMessage] If you change this, also change the other similar ones
pure $
P.wrap "These constructors are not nested beneath their corresponding type names:"
<> P.newline

View File

@ -12,6 +12,8 @@ module Unison.Names
filterByHQs,
filterBySHs,
filterTypes,
fromReferenceIds,
fromUnconflictedReferenceIds,
map,
makeAbsolute,
makeRelative,
@ -69,7 +71,7 @@ import Unison.Name (Name)
import Unison.Name qualified as Name
import Unison.NameSegment (NameSegment)
import Unison.Prelude
import Unison.Reference (Reference, TermReference, TypeReference)
import Unison.Reference (Reference, TermReference, TermReferenceId, TypeReference, TypeReferenceId)
import Unison.Reference qualified as Reference
import Unison.Referent (Referent)
import Unison.Referent qualified as Referent
@ -105,6 +107,22 @@ instance Monoid (Names) where
isEmpty :: Names -> Bool
isEmpty n = R.null n.terms && R.null n.types
-- | Construct a 'Names' from unconflicted reference ids.
fromReferenceIds :: DefnsF (Relation Name) TermReferenceId TypeReferenceId -> Names
fromReferenceIds defns =
Names
{ terms = Relation.mapRan Referent.fromTermReferenceId defns.terms,
types = Relation.mapRan Reference.fromId defns.types
}
-- | Construct a 'Names' from unconflicted reference ids.
fromUnconflictedReferenceIds :: DefnsF (Map Name) TermReferenceId TypeReferenceId -> Names
fromUnconflictedReferenceIds defns =
Names
{ terms = Relation.fromMap (Map.map Referent.fromTermReferenceId defns.terms),
types = Relation.fromMap (Map.map Reference.fromId defns.types)
}
map :: (Name -> Name) -> Names -> Names
map f (Names {terms, types}) = Names terms' types'
where
@ -542,7 +560,7 @@ lenientToNametree names =
(lenientRelationToNametree names.terms)
(lenientRelationToNametree names.types)
where
lenientRelationToNametree :: Ord a => Relation Name a -> Nametree (Map NameSegment a)
lenientRelationToNametree :: (Ord a) => Relation Name a -> Nametree (Map NameSegment a)
lenientRelationToNametree =
-- The partial `Set.findMin` is fine here because Relation.domain only has non-empty Set values. A NESet would be
-- better.

View File

@ -0,0 +1,10 @@
module Unison.Util.Conflicted
( Conflicted (..),
)
where
import Data.Set.NonEmpty (NESet)
-- | A conflicted thing.
data Conflicted n a
= Conflicted !n !(NESet a)

View File

@ -55,6 +55,7 @@ library
Unison.Type
Unison.Type.Names
Unison.Util.Components
Unison.Util.Conflicted
Unison.Util.Defn
Unison.Util.Defns
Unison.Util.Nametree

View File

@ -92,10 +92,14 @@ scratch/ns2> update
scratch/main> diff.namespace /ns1: /ns2:
scratch/ns2> alias.term d d'
scratch/ns2> alias.type A A'
scratch/ns2> alias.term A.A A'.A
scratch/ns2> alias.type X X'
scratch/ns2> alias.term X.x X'.x
scratch/main> diff.namespace /ns1: /ns2:
scratch/ns1> alias.type X X2
scratch/ns1> alias.term X.x X2.x
scratch/ns2> alias.type A' A''
scratch/ns2> alias.term A'.A A''.A
scratch/ns2> branch /ns3
scratch/ns2> alias.term fromJust' yoohoo
scratch/ns2> delete.term.verbose fromJust'

View File

@ -199,10 +199,18 @@ scratch/ns2> alias.type A A'
Done.
scratch/ns2> alias.term A.A A'.A
Done.
scratch/ns2> alias.type X X'
Done.
scratch/ns2> alias.term X.x X'.x
Done.
scratch/main> diff.namespace /ns1: /ns2:
Resolved name conflicts:
@ -238,17 +246,29 @@ scratch/main> diff.namespace /ns1: /ns2:
16. X 17. X' (added)
18. fromJust' ┐ 19. fromJust#gjmq673r1v (removed)
20. fromJust#gjmq673r1v ┘
18. A.A 19. A'.A (added)
20. fromJust' ┐ 21. fromJust#gjmq673r1v (removed)
22. fromJust#gjmq673r1v ┘
23. X.x 24. X'.x (added)
scratch/ns1> alias.type X X2
Done.
scratch/ns1> alias.term X.x X2.x
Done.
scratch/ns2> alias.type A' A''
Done.
scratch/ns2> alias.term A'.A A''.A
Done.
scratch/ns2> branch /ns3
Done. I've created the ns3 branch based off of ns2.

View File

@ -1,6 +1,6 @@
# Update on conflict
Updating conflicted definitions works fine.
Conflicted definitions prevent `update` from succeeding.
```ucm:hide
scratch/main> builtins.merge lib.builtins
@ -21,7 +21,6 @@ scratch/main> delete.term temp
x = 3
```
```ucm
```ucm:error
scratch/main> update
scratch/main> view x
```

View File

@ -1,6 +1,6 @@
# Update on conflict
Updating conflicted definitions works fine.
Conflicted definitions prevent `update` from succeeding.
``` unison
x = 1
@ -59,14 +59,7 @@ x = 3
``` ucm
scratch/main> update
Okay, I'm searching the branch for code that needs to be
updated...
Done.
scratch/main> view x
x : Nat
x = 3
The term name x is ambiguous. Please resolve the ambiguity,
then try to update again.
```

View File

@ -70,6 +70,11 @@ myproject/main> update
```
``` unison:added-by-ucm scratch.u
foo = +30
-- The definitions below are not compatible with the updated definitions above.
-- Please fix the errors and run `update` again.
bar : Nat
bar =
use Nat +
@ -85,6 +90,5 @@ d.y.y.y.y =
use Nat +
foo + 10
foo = +30
```

View File

@ -68,12 +68,16 @@ scratch/main> update
```
``` unison:added-by-ucm scratch.u
foo : Int
foo = +5
-- The definitions below are not compatible with the updated definitions above.
-- Please fix the errors and run `update` again.
bar : Nat
bar =
use Nat +
foo + 10
foo : Int
foo = +5
```

View File

@ -51,10 +51,14 @@ scratch/main> update
```
``` unison:added-by-ucm scratch.u
foo n = "hello, world!"
-- The definitions below are not compatible with the updated definitions above.
-- Please fix the errors and run `update` again.
test> mynamespace.foo.test =
n = 2
if foo n == 2 then [Ok "passed"] else [Fail "wat"]
foo n = "hello, world!"
```

View File

@ -15,9 +15,6 @@ scratch/main> alias.term Foo.Bar Foo.BarAlias
unique type Foo = Bar Nat Nat
```
Bug: we leave `Foo.BarAlias` in the namespace with a nameless decl.
```ucm
```ucm:error
scratch/main> update
scratch/main> find.verbose
```

View File

@ -45,27 +45,18 @@ unique type Foo = Bar Nat Nat
type Foo
```
Bug: we leave `Foo.BarAlias` in the namespace with a nameless decl.
``` ucm
scratch/main> update
Okay, I'm searching the branch for code that needs to be
updated...
Done.
scratch/main> find.verbose
1. -- #8fk6k0j208th1ia4vnjtoc5fomd6le540prec255svg71bcfga9dofrvoq1d7v6010d6b6em4q51p8st5c5juhrev72cnnel8ko3o1g
type Foo
2. -- #8fk6k0j208th1ia4vnjtoc5fomd6le540prec255svg71bcfga9dofrvoq1d7v6010d6b6em4q51p8st5c5juhrev72cnnel8ko3o1g#0
Foo.Bar : Nat -> Nat -> Foo
3. -- #b509v3eg4kehsg29g6pvrogeb71ue32nm2fj9284n4i7lprsr7u9a7g6s695d09du0fsfti6rrsk1s62q5thpr1jjkqb3us3s0lrd60#0
Foo.BarAlias : Nat -> #b509v3eg4k
Sorry, I wasn't able to perform the update:
The type Foo has a constructor with multiple names, and I
can't perform an update in this situation:
* Foo.Bar
* Foo.BarAlias
Please delete all but one name for each constructor, and then
try updating again.
```

View File

@ -65,11 +65,15 @@ scratch/main> update
```
``` unison:added-by-ucm scratch.u
type Foo = Bar Nat
-- The definitions below are not compatible with the updated definitions above.
-- Please fix the errors and run `update` again.
foo : Foo -> Nat
foo = cases
Bar n -> n
Baz n m -> n Nat.+ m
type Foo = Bar Nat
```

View File

@ -104,6 +104,11 @@ scratch/main> find.verbose
```
``` unison:added-by-ucm scratch.u
type Foo = { bar : Nat }
-- The definitions below are not compatible with the updated definitions above.
-- Please fix the errors and run `update` again.
Foo.baz : Foo -> Int
Foo.baz = cases Foo _ baz -> baz
@ -113,6 +118,5 @@ Foo.baz.modify f = cases Foo bar baz -> Foo bar (f baz)
Foo.baz.set : Int -> Foo -> Foo
Foo.baz.set baz1 = cases Foo bar _ -> Foo bar baz1
type Foo = { bar : Nat }
```

View File

@ -54,15 +54,13 @@ scratch/main> view Foo
scratch/main> update
Okay, I'm searching the branch for code that needs to be
updated...
I couldn't complete the update because the type Foo has
unnamed constructors. (I currently need each constructor to
have a name somewhere under the type name.)
Sorry, I wasn't able to perform the update:
The type Foo has some constructors with missing names, and I
can't perform an update in this situation.
You can use `view Foo` and
`alias.term <hash> Foo.<ConstructorName>` to give names to
each constructor, and then try the update again.
each unnamed constructor, and then try the update again.
```

View File

@ -17,10 +17,6 @@ scratch/main> add
unique type Foo = Bar Nat Nat
```
Bug: we want this update to be rejected earlier, because it violates the "decl coherency" precondition that there's
only one name for each constructor. We instead get too far in the update process, and are delivered a bogus scratch.u
file to stare at.
```ucm:error
scratch/main> update
```

View File

@ -48,28 +48,12 @@ unique type Foo = Bar Nat Nat
type Foo
```
Bug: we want this update to be rejected earlier, because it violates the "decl coherency" precondition that there's
only one name for each constructor. We instead get too far in the update process, and are delivered a bogus scratch.u
file to stare at.
``` ucm
scratch/main> update
Okay, I'm searching the branch for code that needs to be
updated...
That's done. Now I'm making sure everything typechecks...
Typechecking failed. I've updated your scratch file with the
definitions that need fixing. Once the file is compiling, try
`update` again.
The type A.B is an alias of A. I'm not able to perform an
update when a type exists nested under an alias of itself.
Please separate them or delete one copy, and then try updating
again.
```
``` unison:added-by-ucm scratch.u
structural type A = B.OneAlias Foo
structural type A.B = OneAlias Foo
type Foo = Bar Nat Nat
```

View File

@ -15,9 +15,6 @@ scratch/main> alias.term Foo.Bar Stray.BarAlias
unique type Foo = Bar Nat Nat
```
Bug: we leave `Stray.BarAlias` in the namespace with a nameless decl.
```ucm
```ucm:error
scratch/main> update
scratch/main> find.verbose
```

View File

@ -45,27 +45,16 @@ unique type Foo = Bar Nat Nat
type Foo
```
Bug: we leave `Stray.BarAlias` in the namespace with a nameless decl.
``` ucm
scratch/main> update
Okay, I'm searching the branch for code that needs to be
updated...
Done.
scratch/main> find.verbose
1. -- #8fk6k0j208th1ia4vnjtoc5fomd6le540prec255svg71bcfga9dofrvoq1d7v6010d6b6em4q51p8st5c5juhrev72cnnel8ko3o1g
type Foo
2. -- #8fk6k0j208th1ia4vnjtoc5fomd6le540prec255svg71bcfga9dofrvoq1d7v6010d6b6em4q51p8st5c5juhrev72cnnel8ko3o1g#0
Foo.Bar : Nat -> Nat -> Foo
3. -- #b509v3eg4kehsg29g6pvrogeb71ue32nm2fj9284n4i7lprsr7u9a7g6s695d09du0fsfti6rrsk1s62q5thpr1jjkqb3us3s0lrd60#0
Stray.BarAlias : Nat -> #b509v3eg4k
Sorry, I wasn't able to perform the update, because I need all
constructor names to be nested somewhere beneath the
corresponding type name.
The constructor Stray.BarAlias is not nested beneath the
corresponding type name. Please either use `move` to move it,
or if it's an extra copy, you can simply `delete` it. Then try
the update again.
```

View File

@ -56,15 +56,13 @@ scratch/main> view Foo
scratch/main> update
Okay, I'm searching the branch for code that needs to be
updated...
I couldn't complete the update because the type Foo has
unnamed constructors. (I currently need each constructor to
have a name somewhere under the type name.)
Sorry, I wasn't able to perform the update:
The type Foo has some constructors with missing names, and I
can't perform an update in this situation.
You can use `view Foo` and
`alias.term <hash> Foo.<ConstructorName>` to give names to
each constructor, and then try the update again.
each unnamed constructor, and then try the update again.
```

View File

@ -60,9 +60,13 @@ scratch/main> update
```
``` unison:added-by-ucm scratch.u
type Foo = Bar Nat Nat
-- The definitions below are not compatible with the updated definitions above.
-- Please fix the errors and run `update` again.
incrFoo : Foo -> Foo
incrFoo = cases Bar n -> Bar (n Nat.+ 1)
type Foo = Bar Nat Nat
```

View File

@ -58,8 +58,12 @@ scratch/main> update
```
``` unison:added-by-ucm scratch.u
type Foo a = Bar Nat a
-- The definitions below are not compatible with the updated definitions above.
-- Please fix the errors and run `update` again.
type Baz = Qux Foo
type Foo a = Bar Nat a
```