unisonweb / unison

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

Weird parse/print issue to investigate #5433

Closed mitchellwrosen closed 3 weeks ago

mitchellwrosen commented 3 weeks ago
  1. clone @mitchellwrosen/bug1
  2. Save this scratch file
hello : Request {Constructors} a -> ()
hello = cases
  { constructor () -> _ } -> ()
  { x } -> ()

ability bunq.application.Constructors where
  constructor : '{Constructors} a
  1. Observe the error
  EffectConstructorHadMultipleEffects:
    {Constructors, Constructors} a1612

If you instead write bunq.application.Constructors as either of these

ability bunq.application.Constructors where
  constructor : '{bunq.application.Constructors} a

ability bunq.application.Constructors where
  constructor : 'a

even though Constructors is an unambiguous suffix, then the error goes away. It also goes away if you delete bunq.application.makeWith from the file.

Furthermore, view Constructors renders the latter (with self references as bunq.application.Constructors, which is weird.

Thanks @etorreborre

mitchellwrosen commented 3 weeks ago

During type declaration parsing, we munge the last arrow to add the ability if it isn't there. That means if you write

ability A.B.C where d : () ->{B.C} ()

then we'll parse it as

ability A.B.C where d : () ->{B.C, A.B.C} ()

This isn't necessarily a problem, but it is a weird time to add the ability (maybe?), since we don't know what each name resolves to.

Later when we bind type names we'll end up with

ability A.B.C where d : () ->{A.B.C, A.B.C} ()

The B.C has fully resolved to a local A.B.C reference, so there are two. I think if we don't want to move the "add ability if not present" code out of the decl parser, then we ought to de-dupe at this point. I suspect this is ultimately what's triggering the "duplicate abilities in effect constructor" error.

mitchellwrosen commented 3 weeks ago

Still a mystery to me: why do view and update print different-looking abilities?

For example view foo.Bar will print

ability foo.Bar where baz : '{foo.Bar} ()

(note the full name of the ability self-reference), whereas update will render

ability foo.Bar where baz : '{Bar} ()

if Bar is the shortest unique suffix of foo.Bar.

etorreborre commented 3 weeks ago

Thanks @mitchellwrosen for having a look at this and sorry for not having a smaller reproducible case :-).