unisonweb / unison

A friendly programming language from the future
https://unison-lang.org
Other
5.78k stars 270 forks source link

DatabaseIntegrityError in getWatch #2122

Closed runarorama closed 2 years ago

runarorama commented 3 years ago

In my scratch file:

{{ 
  Compute the [Jaccard similarity index](https://en.wikipedia.org/wiki/Jaccard_index) 
  of two bags, a value from 0 to 0.5 which is their intersection divided by their direct sum. If the bags have no elements in common, their similarity will be `0`. If the bags are identical, their similarity will be `0.5`.

  Example: 

Bag.similarity (Bag.fromText "alice") (Bag.fromText "alicia")


  }}
Bag.similarity: Bag a -> Bag a -> Float
Bag.similarity a b = toFloat (size (intersect a b)) / toFloat (size (a + b))

Text.similarity : Text -> Text -> Float
Text.similarity a b = 
  f t = Bag.fromList (slidingPairs t)
  Bag.similarity (f a) (f b)

test> slidingPairs.tests.concat = runs 100 'let
  t = !ascii
  s = size t
  ps = slidingPairs t
  fst = Text.fromCharList (map at1 ps)
  snd = Text.fromCharList (map at2 ps)
  expect (fst == take (drop s 1) t && (snd == drop 1 t))

{{ 
  Returns a list of all adjacent character pairs in the text, in the order
  that they appear.

  For example:

slidingPairs "alice"

}}
slidingPairs : Text -> [(Char, Char)]
slidingPairs t =
  pair t = match toCharList (take 2 t) with
    [a,b] -> Some ((a,b), drop 1 t)
    _ -> None
  unfold t pair

Get the docs:

.> docs Bag.similarity

Crashes with

ucm: DatabaseIntegrityError (NoObjectForPrimaryHashId (HashId 4603)) in getWatch
CallStack (from HasCallStack):
  error, called at src/Unison/Codebase/SqliteCodebase.hs:295:88 in unison-parser-typechecker-0.0.0-DaPEC8BhFLfBuvI7Fapoon:Unison.Codebase.SqliteCodebase
  getCycleLen, called at src/Unison/Codebase/SqliteCodebase.hs:571:34 in unison-parser-typechecker-0.0.0-DaPEC8BhFLfBuvI7Fapoon:Unison.Codebase.SqliteCodebase

If I first add, then docs succeeds.

pchiusano commented 3 years ago

@runarorama I've hit this but don't have a reliable repro.

Try bouncing ucm and/or debug.clear-cache to workaround.

jindraivanek commented 3 years ago

I can reliably reproduce same crash with this scratch file:

use .base

type Digit = Digit (Set Nat)
type Sudoku = Sudoku [Digit]
full = Set.fromList [1,2,3,4,5,6,7,8,9]

betweenChars c1 c2 c = (c1 <= c) && (c <= c2)
parseSudoku s = 
    chars = s |> Text.toCharList |> List.filter (c -> (betweenChars ?1 ?9 c) || (betweenChars ?. ?. c))
    chars |> List.map (cases
        ?. -> Digit full
        c -> Digit (Set.fromList [Nat.drop (Char.toNat c) (Char.toNat ?0)])
    ) |> Sudoku

> parseSudoku ex1

ex1 = "
6.......7
....9..2.
3.1..259.
8....7.13
....8....
76.3....8
.782..1.6
.5..3....
2.......9"

On empty codebase (with pulled .base), I get this after second save of scratch file:

  I found and typechecked these definitions in ~/unison/unison-sandbox/sudokuBug.u. If you do an
  `add` or `update`, here's how your codebase would change:

    ⍟ These new definitions are ok to `add`:

      type Digit
      type Sudoku
      betweenChars : c1 -> c1 -> c1 -> Boolean
      ex1          : Text
      full         : Set Nat
      parseSudoku  : Text -> Sudoku

  Now evaluating any watch expressions (lines starting with `>`)... Ctrl+C cancels.

ucm: DatabaseIntegrityError (NoObjectForPrimaryHashId (HashId 6749)) in getWatch
CallStack (from HasCallStack):
  error, called at src/Unison/Codebase/SqliteCodebase.hs:295:88 in unison-parser-typechecker-0.0.0-2ZZpIeQc0fn4bLbpvD8Zs0:Unison.Codebase.SqliteCodebase
  getCycleLen, called at src/Unison/Codebase/SqliteCodebase.hs:571:34 in unison-parser-typechecker-0.0.0-2ZZpIeQc0fn4bLbpvD8Zs0:Unison.Codebase.SqliteCodebase

Next time on same codebase it crashes at first save.

With debug.clear-cache it needs 2x save again to crash.

After add and save, I got Segmentation fault.

Environment

release/M2g

Windows10 - WSL - Ubuntu 20.04.1

ChrisPenner commented 2 years ago

I've confirmed that saving this scratch file twice crashes on trunk but does NOT crash on topic/rehash-codebase (with a migrated version of base)

use .base

structural type Digit = Digit (Set Nat)
structural type Sudoku = Sudoku [Digit]
full = Set.fromList [1,2,3,4,5,6,7,8,9]

betweenChars c1 c2 c = (Char.toNat c1 <= Char.toNat c) && (Char.toNat c <= Char.toNat c2)
parseSudoku s = 
    chars = s |> Text.toCharList |> List.filter (c -> (betweenChars ?1 ?9 c) || (betweenChars ?. ?. c))
    chars |> List.map (cases
        ?. -> Digit full
        c -> Digit (Set.fromList [Nat.drop (Char.toNat c) (Char.toNat ?0)])
    ) |> Sudoku

> parseSudoku ex1

ex1 = "
6.......7
....9..2.
3.1..259.
8....7.13
....8....
76.3....8
.782..1.6
.5..3....
2.......9"
ChrisPenner commented 2 years ago

Done in #2627 🎉