Skip to content

Commit

Permalink
block extension method with 2+ type parameter lists
Browse files Browse the repository at this point in the history
  • Loading branch information
bishabosha committed Feb 15, 2021
1 parent 9e83a60 commit 7927353
Show file tree
Hide file tree
Showing 7 changed files with 64 additions and 8 deletions.
13 changes: 5 additions & 8 deletions src/compiler/scala/tools/nsc/tasty/TreeUnpickler.scala
Expand Up @@ -734,24 +734,21 @@ class TreeUnpickler[Tasty <: TastyUniverse](
val isMacro = repr.originalFlagSet.is(Erased | Macro)
checkUnsupportedFlags(repr.tastyOnlyFlags &~ (Extension | Exported | Infix | optFlag(isMacro)(Erased)))
val isCtor = sym.isConstructor
val paramDefss = readParamss(skipTypeParams=isCtor)(localCtx) // TODO: this can mix type and term parameters, must skip type params if ctor
val paramDefss = readParamss(skipTypeParams=isCtor)(localCtx)
val typeParams: List[Symbol] = {
if (isCtor) {
// skipTypeParams()
sym.owner.typeParams
}
else {
// readParams[NoCycle](TYPEPARAM)(localCtx).map(symFromNoCycle)

// TODO: Handle extension methods with multiple param lists
val first = paramDefss.take(1).flatten.map(symFromNoCycle)
if (first.headOption.exists(_.isType)) first else Nil
}
}
val vparamss: List[List[NoCycle]] = {
// TODO: Handle extension methods with multiple param lists
val droppedClauses = if (typeParams.isEmpty) 0 else 1
paramDefss.drop(droppedClauses).ensuring(_.flatten.forall(nc => symFromNoCycle(nc).isTerm))
val valueClauses = paramDefss.drop(if (typeParams.isEmpty) 0 else 1)
val hasTypeParams = valueClauses.exists(_.exists(nc => symFromNoCycle(nc).isType))
unsupportedWhen(hasTypeParams, s"extension method with secondary type parameter list: $tname")
valueClauses
}
val tpt = readTpt()(localCtx)
if (isMacro) {
Expand Down
4 changes: 4 additions & 0 deletions test/tasty/neg/src-2/TestDependentExtension.check
@@ -0,0 +1,4 @@
TestDependentExtension_fail.scala:11: error: Unsupported Scala 3 extension method with secondary type parameter list: extract; found in trait tastytest.DependentExtension.
val res = implicitly[DependentExtension].extract(box)(_ + 1)
^
1 error
15 changes: 15 additions & 0 deletions test/tasty/neg/src-2/TestDependentExtension_fail.scala
@@ -0,0 +1,15 @@
package tastytest

object TestDependentExtension {
import DependentExtension._

def test = {
val box = new Box {
type Repr = Int
val value: Int = 23
}
val res = implicitly[DependentExtension].extract(box)(_ + 1)
assert(res == 24)
}

}
4 changes: 4 additions & 0 deletions test/tasty/neg/src-2/TestRealFunctor.check
@@ -0,0 +1,4 @@
TestRealFunctor_fail.scala:6: error: Unsupported Scala 3 extension method with secondary type parameter list: map; found in trait tastytest.RealFunctor.
def map[A, B](fa: List[A])(f: A => B): List[B] = fa.map(f)
^
1 error
9 changes: 9 additions & 0 deletions test/tasty/neg/src-2/TestRealFunctor_fail.scala
@@ -0,0 +1,9 @@
package tastytest

object TestRealFunctor {
// in this test, we try to implement an extension method that has two type-parameter lists
implicit object ListRealFunctor extends RealFunctor[List] {
def map[A, B](fa: List[A])(f: A => B): List[B] = fa.map(f)
}

}
20 changes: 20 additions & 0 deletions test/tasty/neg/src-3/DependentExtension.scala
@@ -0,0 +1,20 @@
package tastytest

import DependentExtension.Box

// `DependentExtension` uses two type parameter lists in its `extract` method. the second type parameter list is
// dependent on the first term parameter list. It is unclear how to interpret this.
trait DependentExtension {
extension [B <: Box](b: B) def extract[R >: b.Repr, O](f: R => O): O = f(b.value)
}

object DependentExtension {

given DependentExtension with {}

trait Box {
type Repr
val value: Repr
}

}
7 changes: 7 additions & 0 deletions test/tasty/neg/src-3/RealFunctor.scala
@@ -0,0 +1,7 @@
package tastytest

// This `Functor` uses two type parameter lists in its `map` method.
// In this example, it may be safe to merge the type parameter lists.
trait RealFunctor[F[_]] {
extension [A](fa: F[A]) def map[B](f: A => B): F[B]
}

0 comments on commit 7927353

Please sign in to comment.