Skip to content

Commit

Permalink
Revert "Compensate loss of transitivity" (#21356)
Browse files Browse the repository at this point in the history
This reverts commit 7c4bd67
See [#21344 comment]
(#21344 (comment))

We will have to reconsider how to alleviate the transitory problem
before releasing 3.6.

Fixes #21320
Fixes #21352
  • Loading branch information
EugeneFlesselle authored Aug 9, 2024
2 parents 15a0d05 + 5408a80 commit 6a1db57
Show file tree
Hide file tree
Showing 7 changed files with 171 additions and 15 deletions.
18 changes: 3 additions & 15 deletions compiler/src/dotty/tools/dotc/typer/Implicits.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1385,6 +1385,8 @@ trait Implicits:
def disambiguate(alt1: SearchResult, alt2: SearchSuccess) = alt1 match
case alt1: SearchSuccess =>
var diff = compareAlternatives(alt1, alt2, disambiguate = true)
assert(diff <= 0 || isWarnPriorityChangeVersion)
// diff > 0 candidates should already have been eliminated in `rank`
if diff == 0 && alt1.ref =:= alt2.ref then
diff = 1 // See i12951 for a test where this happens
else if diff == 0 && alt2.isExtension then
Expand Down Expand Up @@ -1636,21 +1638,7 @@ trait Implicits:
validateOrdering(ord)
throw ex

val sorted = sort(eligible)
val res = sorted match
case first :: rest =>
val firstIsImplicit = first.ref.symbol.is(Implicit)
if rest.exists(_.ref.symbol.is(Implicit) != firstIsImplicit) then
// Mixture of implicits and givens
// Rank implicits first, then, if there is a given that it better than the best implicit(s)
// switch over to givens.
val (sortedImplicits, sortedGivens) = sorted.partition(_.ref.symbol.is(Implicit))
val implicitResult = rank(sortedImplicits, NoMatchingImplicitsFailure, Nil)
rank(sortedGivens, implicitResult, Nil)
else
rank(sorted, NoMatchingImplicitsFailure, Nil)
case _ =>
NoMatchingImplicitsFailure
val res = rank(sort(eligible), NoMatchingImplicitsFailure, Nil)

// Issue all priority change warnings that can affect the result
val shownWarnings = priorityChangeWarnings.toList.collect:
Expand Down
File renamed without changes.
73 changes: 73 additions & 0 deletions tests/pos/i21320b.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import scala.deriving.*
import scala.compiletime.*

trait ConfigMonoid[T]:
def zero: T
def orElse(main: T, defaults: T): T

object ConfigMonoid:
given option[T]: ConfigMonoid[Option[T]] = ???

inline def zeroTuple[C <: Tuple]: Tuple =
inline erasedValue[C] match
case _: EmptyTuple => EmptyTuple
case _: (t *: ts) =>
summonInline[ConfigMonoid[t]].zero *: zeroTuple[ts]

inline def valueTuple[C <: Tuple, T](index: Int, main: T, defaults: T): Tuple =
inline erasedValue[C] match
case _: EmptyTuple => EmptyTuple
case _: (t *: ts) =>
def get(v: T) = v.asInstanceOf[Product].productElement(index).asInstanceOf[t]
summonInline[ConfigMonoid[t]].orElse(get(main), get(defaults)) *: valueTuple[ts, T](
index + 1,
main,
defaults
)

inline given derive[T](using m: Mirror.ProductOf[T]): ConfigMonoid[T] =
new ConfigMonoid[T]:
def zero: T = m.fromProduct(zeroTuple[m.MirroredElemTypes])
def orElse(main: T, defaults: T): T = m.fromProduct(valueTuple[m.MirroredElemTypes, T](0, main, defaults))



final case class PublishOptions(
v1: Option[String] = None,
v2: Option[String] = None,
v3: Option[String] = None,
v4: Option[String] = None,
v5: Option[String] = None,
v6: Option[String] = None,
v7: Option[String] = None,
v8: Option[String] = None,
v9: Option[String] = None,
ci: PublishContextualOptions = PublishContextualOptions(),
)
object PublishOptions:
implicit val monoid: ConfigMonoid[PublishOptions] = ConfigMonoid.derive

final case class PublishContextualOptions(
v1: Option[String] = None,
v2: Option[String] = None,
v3: Option[String] = None,
v4: Option[String] = None,
v5: Option[String] = None,
v6: Option[String] = None,
v7: Option[String] = None,
v8: Option[String] = None,
v9: Option[String] = None,
v10: Option[String] = None,
v11: Option[String] = None,
v12: Option[String] = None,
v13: Option[String] = None,
v14: Option[String] = None,
v15: Option[String] = None,
v16: Option[String] = None,
v17: Option[String] = None,
v18: Option[String] = None,
v19: Option[String] = None,
v20: Option[String] = None
)
object PublishContextualOptions:
implicit val monoid: ConfigMonoid[PublishContextualOptions] = ConfigMonoid.derive // was crash
19 changes: 19 additions & 0 deletions tests/pos/i21352a/schema.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//> using options -source:3.5

case class Schema[T](format: String):
def asOption: Schema[Option[T]] = ???
def name(name: Option[SName]): Schema[T] = ???
def format(f: String): Schema[T] = ???

object Schema extends SchemaCompanionMacros:
implicit def schemaForOption[T: Schema]: Schema[Option[T]] =
implicitly[Schema[T]]
???

trait SchemaCompanionMacros extends SchemaDerivation:
given derivedStringBasedUnionEnumeration[S](using IsUnionOf[String, S]): Schema[S] =
val x: Schema[S] = ???
x.name(None)

@main def Test =
case class Foo(x: Int) derives Schema
26 changes: 26 additions & 0 deletions tests/pos/i21352a/schemaDerivation.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//> using options -source:3.5

import scala.deriving.*
import scala.quoted.*

trait SName
abstract class CaseClass[Typeclass[_], Type]:
def param: CaseClass.Param[Typeclass, Type]

object CaseClass:
trait Param[Typeclass[_], Type]:
type PType
def typeclass: Typeclass[PType]


sealed trait IsUnionOf[T, A]
object IsUnionOf:
transparent inline given derived[T, A]: IsUnionOf[T, A] = ${ deriveImpl[T, A] }
private def deriveImpl[T, A](using quotes: Quotes): Expr[IsUnionOf[T, A]] = ???

trait SchemaDerivation:
inline implicit def derived[T](implicit m: Mirror.Of[T]): Schema[T] =
val ctx: CaseClass[Schema, T] = ???
val valueSchema = ctx.param.typeclass
val format = valueSchema.format
???
33 changes: 33 additions & 0 deletions tests/pos/i21352b.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@

object serializer:
trait Reader[T]
trait Writer[T]
// Needs to be implicit val
implicit val UnitReader: Reader[Unit] = ???
implicit val StringReader: Reader[String] = ???
// A way to derive instances needs to be available
inline given superTypeReader[T: scala.reflect.ClassTag]: Reader[T] = ???
import serializer.Reader

trait Codec[T]
trait Channel[F[_]]:
def notificationStub[In: Codec](): In => F[Unit]
trait Monadic[F[_]]

sealed abstract class LSPNotification():
type In
given inputReader: Reader[In]

class PreparedNotification[X <: LSPNotification](val x: X, val in: x.In):
type In = x.In

trait Communicate[F[_]]:
def notification[X <: LSPNotification](notif: X, in: notif.In): F[Unit]

object Communicate:
given codec[T: Reader]: Codec[T] = ???

def channel[F[_]: Monadic](channel: Channel[F]) =
new Communicate[F]:
override def notification[X <: LSPNotification](notif: X, in: notif.In): F[Unit] =
channel.notificationStub().apply(in) // was error
17 changes: 17 additions & 0 deletions tests/pos/i21352c.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@

trait Text[T]
trait Read[A]
object Read extends ReadImplicits:
implicit val unit: Read[Unit] = ???
trait ReadImplicits:
import scala.deriving.*
given roe: Read[Option[EmptyTuple]] = ???
given rou: Read[Option[Unit]] = ???
given cons1[H, T <: Tuple](using Read[Option[H]], Read[Option[T]]): Read[Option[H *: T]] = ???

trait Fragment:
def query[B: Read]: String = ???

@main def Test =
val f: Fragment = ???
f.query // was error

0 comments on commit 6a1db57

Please sign in to comment.