Skip to content

rf: type unification for type patterns #6

@mdempsky

Description

@mdempsky

The normal semantics for var t T in an ex rule is that t will match any expression whose type is assignable to T. In the example below, i and v are both assignable to I, which implements interface { Equal(I) bool }, so I would expect all of the equals to be rewritten. However, currently only the first gets rewritten:

ex {
  type T interface { Equal(T) bool }
  var t1, t2 T
  t1 == t2 -> t1.Equal(t2)
}
-- x.go --
package p

type I interface { Equal(I) bool }
var i I

type V int
func (V) Equal(I) bool
var v V
var _ I = v

var _ = i == i
var _ = i == v
var _ = v == i
var _ = v == v

I suspect matcher.matchWildcardType needs to be extended to support type unification rather than requiring strict type identity for back matches.

There's probably some subtlety here for preferring that the unification to prefer unifying to I rather than interface { Equal(I) bool }. Might want to learn from how types2 handles this.

In the mean time, it's possible to manually workaround this without too many additional rules:

ex {
  type A interface{ Equal(A) bool }
  type B interface{ Equal(A) bool }

  var a1, a2 A
  var b1, b2 B

  a1 == a2 -> a1.Equal(a2)
  a1 == b2 -> a1.Equal(b2)
  b1 == a2 -> b1.Equal(a2)
  b1 == b2 -> b1.Equal(b2)
}
-- x.go --
package p

type I interface{ Equal(I) bool }
var i I

type V int
func (V) Equal(I) bool
var v V
var _ I = v

var _ = i == i
var _ = i == v
var _ = v == i
var _ = v == v

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions