diff --git a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala index ecf1da30cac1..7bfe00aea13e 100644 --- a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala +++ b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala @@ -11,7 +11,7 @@ import Constants.* import util.{Stats, SimpleIdentityMap, SimpleIdentitySet} import Decorators.* import Uniques.* -import Flags.Method +import Flags.{Method, Transparent} import inlines.Inlines import config.Printers.typr import Inferencing.* @@ -108,7 +108,7 @@ object ProtoTypes { res /** Constrain result with two special cases: - * 1. If `meth` is an inlineable method in an inlineable context, + * 1. If `meth` is a transparent inlineable method in an inlineable context, * we should always succeed and not constrain type parameters in the expected type, * because the actual return type can be a subtype of the currently known return type. * However, we should constrain parameters of the declared return type. This distinction is @@ -128,11 +128,12 @@ object ProtoTypes { case _ => false - if Inlines.isInlineable(meth) then + if Inlines.isInlineable(meth) && meth.is(Transparent) then constrainResult(mt, wildApprox(pt)) true else constFoldException(pt) || constrainResult(mt, pt) + end constrainResult end Compatibility diff --git a/tests/neg/i18123.check b/tests/neg/i18123.check new file mode 100644 index 000000000000..d784c4d12673 --- /dev/null +++ b/tests/neg/i18123.check @@ -0,0 +1,12 @@ +-- [E172] Type Error: tests/neg/i18123.scala:25:33 --------------------------------------------------------------------- +25 | (charClassIntersection.rep() | classItem.rep()) // error + | ^^^^^^^^^^^^^^^ + |No given instance of type pkg.Implicits.Repeater[pkg.RegexTree, V] was found. + |I found: + | + | pkg.Implicits.Repeater.GenericRepeaterImplicit[T] + | + |But method GenericRepeaterImplicit in object Repeater does not match type pkg.Implicits.Repeater[pkg.RegexTree, V] + | + |where: V is a type variable with constraint <: Seq[pkg.CharClassIntersection] + |. diff --git a/tests/neg/i18123.scala b/tests/neg/i18123.scala new file mode 100644 index 000000000000..bb220dc78e93 --- /dev/null +++ b/tests/neg/i18123.scala @@ -0,0 +1,25 @@ +// may not compile anymore in Scala 3.4+ +package pkg + +trait P[+T] + +extension [T](inline parse0: P[T]) + inline def | [V >: T](inline other: P[V]): P[V] = ??? + +extension [T](inline parse0: => P[T]) + inline def rep[V](inline min: Int = 0)(using repeater: Implicits.Repeater[T, V]): P[V] = ??? + +object Implicits: + trait Repeater[-T, R] + object Repeater: + implicit def GenericRepeaterImplicit[T]: Repeater[T, Seq[T]] = ??? + +sealed trait RegexTree +abstract class Node extends RegexTree +class CharClassIntersection() extends Node + +def classItem: P[RegexTree] = ??? +def charClassIntersection: P[CharClassIntersection] = ??? + +def x = + (charClassIntersection.rep() | classItem.rep()) // error diff --git a/tests/pos/i18123.scala b/tests/pos/i18123.scala index 714850004d2c..2b18b3fc73c3 100644 --- a/tests/pos/i18123.scala +++ b/tests/pos/i18123.scala @@ -7,7 +7,8 @@ extension [T](inline parse0: P[T]) inline def | [V >: T](inline other: P[V]): P[V] = ??? extension [T](inline parse0: => P[T]) - inline def rep[V](inline min: Int = 0)(using repeater: Implicits.Repeater[T, V]): P[V] = ??? + // transparent needed to make this compile in 3.4+ + transparent inline def rep[V](inline min: Int = 0)(using repeater: Implicits.Repeater[T, V]): P[V] = ??? object Implicits: trait Repeater[-T, R] diff --git a/tests/pos/i20297.scala b/tests/pos/i20297.scala new file mode 100644 index 000000000000..ee7ee57045ae --- /dev/null +++ b/tests/pos/i20297.scala @@ -0,0 +1,20 @@ +sealed abstract class Kyo[+T, -S] +opaque type <[+T, -S] >: T = T | Kyo[T, S] + +extension [T, S](v: T < S) + inline def map[U, S2](inline f: T => U < S2): U < (S & S2) = ??? + +class Streams[V] +object Streams: + def emitValue[V](v: V): Unit < Streams[V] = ??? + +opaque type Stream[+T, V, -S] = T < (Streams[V] & S) +object Stream: + extension [T, V, S](s: Stream[T, V, S]) + def reemit[S2, V2](f: V => Unit < (Streams[V2] & S2)): Stream[T, V2, S & S2] = ??? + def filter[S2](f: V => Boolean < S2): Stream[T, V, S & S2] = reemit { v => + f(v).map { + case false => () + case true => Streams.emitValue(v) + } + }