I agree. If the existing mechanism continues to work (and take precedence over the parameter-count mechanism) then there’s no need to address it at the language level. It isn’t uncommon, but is rare enough (and should be encouraged to stay that way)
A note on compatibility, I have been testing the Dotty only factor10/intent library with the Scala 2 tasty reader, and the various given instance definitions they provide for Eq
and Formatter
type classes become ambiguous when reading from Scala 2, as can be demonstrated in a basic test suite: https://github.com/scalacenter/tasty-reader-compat-testkit/blob/master/intent/src/test/scala/ATest.scala
import intent._
class ATest extends TestSuite with Stateless { self =>
import self.{stringExt => test}, test._
implicit val pos: intent.macros.Position = ??? // comment line for illegal macro
implicit val Eq: intent.core.Eq[Int] = ??? // comment line for ambiguous implicit
implicit val format: intent.core.Formatter[Int] = ??? // comment line for ambiguous implicit
test("3 + 3") { // illegal union type intent.core.MapLike
in("should be 6") {
toEqual(expect(3 + 3))(6)
}
}
}
The definitions can be found here for Eq
The ambiguity mentions tryEq
, so I guess this comes under rule 7
Yes, the existing subclass-based mechanism takes precedence over the added disambiguations.
Quill’s materializeSchemaMeta
is a case-in-point. This functionality (currently) uses macros activated by low-priority implicits which synthesize a entity derivation (which is eventually supposed to materialize into SQL). I have gladly ripped out the implicit-ordering code and replaced it with:
summonExpr(given '[SchemaMeta[T]]) match {
case Some(meta) =>
'{ $meta.unquote }
case None =>
'{ new EntityQuery[T]() }
}
This is a very intuitive and beautiful pattern compared to the implicit def trait-extension/override hackery of High/Low ordered implicits that was needed before.
The problem I have with low priority implicits is that I want to put a default instance in the type class companion object that covers type T, which can be overridden in the companion object of type T. Using a low priority base trait with the type class companion object doesn’t help here, because it will still have the same priority as an instance declared in the type T companion final object.
The only trick left then as far as I can understand it is to take a Not[T] implicit evidence for the default instance.