Skip to content

Commit

Permalink
Reinstantiate restriction to transparent inline methods
Browse files Browse the repository at this point in the history
Reverts parts of scala#19922.

Fixes scala#20342, scala#20297

The logic that we should ignore declared result types of inline methods really only applies
to transparent inlines.
  • Loading branch information
odersky committed Jun 11, 2024
1 parent 27a3f80 commit 42cf114
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 4 deletions.
7 changes: 4 additions & 3 deletions compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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.*
Expand Down Expand Up @@ -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
Expand All @@ -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

Expand Down
12 changes: 12 additions & 0 deletions tests/neg/i18123.check
Original file line number Diff line number Diff line change
@@ -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]
|.
25 changes: 25 additions & 0 deletions tests/neg/i18123.scala
Original file line number Diff line number Diff line change
@@ -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
3 changes: 2 additions & 1 deletion tests/pos/i18123.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
20 changes: 20 additions & 0 deletions tests/pos/i20297.scala
Original file line number Diff line number Diff line change
@@ -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)
}
}

0 comments on commit 42cf114

Please sign in to comment.