unisonweb / unison

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

Strange ucm -> update -> scratch file behavior #5429

Open kylegoetz opened 1 month ago

kylegoetz commented 1 month ago

Describe and demonstrate the bug First, begin with this branch, interval-map/bug.

``` ucm
edit Interval

Should then look like this:

type Interval v = Interval v v

add a doc

{{ A closed interval. The lower bound (first parameter) should be less than or equal to the upper bound (second parameter). }}
type Interval v = Interval v v

now update (because you can't add since Interval is still there)

update

**Screenshots**
If applicable, add screenshots to help explain your problem.

What I expect is that `Interval.doc` will get added. What actually happens is a lot of code gets dumped to the scratch file. 300 lines or so like this.

<img width="566" alt="Screenshot 2024-10-25 at 11 57 06 AM" src="https://github.com/user-attachments/assets/1e1515c8-a49f-440f-ac43-3214a74c185a">

**Next confounding thing!**

If you then go through all of ucm's issues with the code one by one, you're basically going to prefix every instance of `__Node` with `internal.` or `internal.__Node` depending on if the referenced `__Node` is the type or data constructor.

Once you get through that, ucm should be complaining about nearly the entire body of `union`. You can fix this by changing the data type of `Ask` in a few places. Replace `union` with this code and now there should be no more issues with the scratch file and you can complete the update:

```` markdown
``` unison
union : IntervalMap v a -> IntervalMap v a ->{Ask (Ord v)} IntervalMap v a
union = cases
  IntervalMap.IntervalMap xs, IntervalMap.IntervalMap ys ->
    use ViewL Nonempty
    use internal.__IntInterval IntInterval.Internal NoInterval.Internal
    use internal.__Node __Node
    use src <| split
    measured' = __measured()
    let
      (Ord.Ord compareInterval) = Ord()
      a >= i = compareInterval a i !== Less
      a > i = compareInterval a i === Greater
      merge2 as bs = match provide measured' do viewl bs with
        EmptyL                      -> as
        Nonempty bs' b@(internal.__Node.__Node i _) ->
          larger = cases
            IntInterval.Internal k _ -> k > i
            NoInterval.Internal      -> bug "larger NoInterval"
          let
            (l, r) = provide measured' do split larger as
            provide measured' do l >< (b <| merge1 r bs')
      merge1 as bs = match provide measured' do viewl as with
        EmptyL                      -> bs
        Nonempty as' a@(internal.__Node.__Node i _) ->
          larger = cases
            IntInterval.Internal k _ -> k >= i
            NoInterval.Internal      -> bug "larger NoInterval"
          let
            (l, r) = provide measured' do split larger as
            provide measured' do (l >< (a <| merge2 as' r))
      IntervalMap.IntervalMap (merge1 xs ys)


**Environment (please complete the following information):**
 - `ucm --version` release/0.5.23
 - OS/Architecture: macOS 15.0.1