Skip to content

Commit

Permalink
fix #25 - Handle a signed name in a TERMREF
Browse files Browse the repository at this point in the history
  • Loading branch information
bishabosha committed Jun 26, 2020
1 parent f21d101 commit 14cd342
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 45 deletions.
47 changes: 8 additions & 39 deletions src/compiler/scala/tools/nsc/tasty/TreeUnpickler.scala
Expand Up @@ -251,7 +251,7 @@ class TreeUnpickler[Tasty <: TastyUniverse](
/** The symbol defined by current definition */
def symbolAtCurrent()(implicit ctx: Context): Symbol = symAtAddr.get(currentAddr) match {
case Some(sym) =>
assert(ctx.owner === sym.owner, s"owner discrepancy for $sym, expected: ${showSym(ctx.owner)}, found: ${showSym(sym.owner)}")
assert(ctx.owner === sym.owner, s"owner discrepancy for ${showSym(sym)}, expected: ${showSym(ctx.owner)}, found: ${showSym(sym.owner)}")
sym
case None =>
createSymbol()
Expand Down Expand Up @@ -408,7 +408,7 @@ class TreeUnpickler[Tasty <: TastyUniverse](
readPackageRef().termRef
case TYPEREF =>
val name = readTastyName()
val pre = readType()
val pre = readType()
if (pre.typeSymbol === defn.ScalaPackage && ( name === nme.And || name === nme.Or) ) {
if (name === nme.And) {
AndType
Expand All @@ -419,17 +419,12 @@ class TreeUnpickler[Tasty <: TastyUniverse](
}
}
else {
mkTypeRef(pre, name, isTerm = false)
mkTypeRef(pre, name, selectingTerm = false)
}
case TERMREF =>
val sname = readTastyName()
val sname = readTastyName()
val prefix = readType()
sname match {
case TastyName.SignedName(name, sig) =>
??? // TermRef(prefix, name, prefix.member(name).atSignature(sig))
case name =>
mkTypeRef(prefix, name, isTerm = true)
}
mkTypeRef(prefix, sname, selectingTerm = true)
case THIS =>
val sym = readType() match {
case tpe: TypeRef => tpe.sym
Expand All @@ -447,7 +442,7 @@ class TreeUnpickler[Tasty <: TastyUniverse](
case RECthis =>
sys.error("RECthis")//readTypeRef().asInstanceOf[RecType].recThis
case TYPEALIAS =>
readType()// TypeAlias(readType())
readType()// TypeAlias(readType())
case SHAREDtype =>
val ref = readAddr()
typeAtAddr.getOrElseUpdate(ref, forkAt(ref).readType())
Expand Down Expand Up @@ -858,7 +853,7 @@ class TreeUnpickler[Tasty <: TastyUniverse](
val tname = readTastyName()
val name = tname.toEncodedTermName

ctx.log(s"completing member $name at $symAddr. (sym=${showSym(sym)})")
ctx.log(s"completing member $name at $symAddr. ${showSym(sym)}")

val completer = sym.completer

Expand Down Expand Up @@ -949,7 +944,7 @@ class TreeUnpickler[Tasty <: TastyUniverse](
}
case _ => sys.error(s"Reading new member with tag ${astTagToString(tag)}")
}
ctx.log(s"typed { ($sym # ${sym.hashCode}): ${sym.tpe} } in (owner=${showSym(sym.owner)})")
ctx.log(s"typed ${showSym(sym)} : ${sym.tpe} in owner ${showSym(sym.owner)}")
goto(end)
noCycle
}
Expand Down Expand Up @@ -1272,32 +1267,6 @@ class TreeUnpickler[Tasty <: TastyUniverse](
readIndexedParams(tag)
}

def selectFromSig(qualType: Type, name: Name, sig: Signature[Type])(implicit ctx: Context): Type = {
ctx.log(s"looking for overloaded method on $qualType.$name of signature ${sig.show}")
val MethodSignature(args, ret) = sig
var seenTypeParams = false
val (tyParamCount, argsSyms) = {
val (tyParamCounts, params) = args.partitionMap(identity)
assertTasty(tyParamCounts.length <= 1, s"Multiple type parameter lists on signature ${sig.show} for member $name.")
(tyParamCounts.headOption.getOrElse(0), params)
}
val member = qualType.member(name)
val alts = member.asTerm.alternatives
val tpeOpt = alts.find { sym =>
val method = sym.asMethod
val params = method.paramss.flatten
method.returnType.erasure =:= ret &&
params.length === argsSyms.length &&
((name === nme.CONSTRUCTOR && tyParamCount === member.owner.typeParams.length)
|| tyParamCount === method.typeParams.length) &&
params.zip(argsSyms).forall { case (param, tpe) => param.tpe.erasure =:= tpe }
}.map(_.tpe).ensuring(_.isDefined, s"No matching overload of $name with signature ${sig.show}")
var Some(tpe) = tpeOpt
if (name === nme.CONSTRUCTOR && tyParamCount > 0) tpe = mkPolyType(member.owner.typeParams, tpe)
ctx.log(s"selected $tpe")
tpe
}

def completeSelection[T](name: TastyName, sig: Signature[Type], isTerm: Boolean)(f: (Context, Name, (Context, Name, Type) => Type) => T)(implicit ctx: Context): T = {
val encoded = name.toEncodedTermName
val selector = if (isTerm) encoded else encoded.toTypeName
Expand Down
31 changes: 30 additions & 1 deletion src/compiler/scala/tools/nsc/tasty/bridge/SymbolOps.scala
@@ -1,8 +1,13 @@
package scala.tools.nsc.tasty.bridge

import scala.tools.nsc.tasty.SafeEq

import scala.tools.nsc.tasty.TastyUniverse
import scala.tools.nsc.tasty.Signature
import scala.tools.nsc.tasty.Signature.MethodSignature

trait SymbolOps extends TastyKernel { self: TastyUniverse =>
import Contexts.Context

object SymbolOps {
implicit class SymbolDecorator(sym: Symbol) {
Expand All @@ -26,5 +31,29 @@ trait SymbolOps extends TastyKernel { self: TastyUniverse =>
}
}

def showSym(sym: Symbol): String = s"$sym # ${sym.hashCode}"
def selectSymFromSig(qualType: Type, name: Name, sig: Signature[Type])(implicit ctx: Context): Option[(Int, Symbol)] = {
ctx.log(s"""looking for overloaded method [$qualType]("$name") @@ ${sig.show}""")
val MethodSignature(args, ret) = sig
var seenTypeParams = false
val member = qualType.member(name)
val (tyParamCount, argsSyms) = {
val (tyParamCounts, params) = args.partitionMap(identity)
if (tyParamCounts.length > 1) {
reporter.error(noPosition, s"Multiple type parameter lists on signature ${sig.show} for $member.")
}
(tyParamCounts.headOption.getOrElse(0), params)
}
val alts = member.asTerm.alternatives
alts.find { sym =>
val method = sym.asMethod
val params = method.paramss.flatten
method.returnType.erasure =:= ret &&
params.length === argsSyms.length &&
((name === nme.CONSTRUCTOR && tyParamCount === member.owner.typeParams.length)
|| tyParamCount === method.typeParams.length) &&
params.zip(argsSyms).forall { case (param, tpe) => param.tpe.erasure =:= tpe }
}.map(tyParamCount -> _)
}

def showSym(sym: Symbol): String = s"Symbol($sym, #${sym.hashCode})"
}
39 changes: 34 additions & 5 deletions src/compiler/scala/tools/nsc/tasty/bridge/TypeOps.scala
Expand Up @@ -8,6 +8,7 @@ import scala.tools.nsc.tasty.Names.TastyName.SimpleName

import scala.tools.nsc.tasty._
import scala.tools.nsc.tasty.Names.TastyName.ModuleName
import scala.tools.nsc.tasty.Names.TastyName.SignedName

trait TypeOps extends TastyKernel { self: TastyUniverse =>
import Contexts._
Expand Down Expand Up @@ -97,12 +98,40 @@ trait TypeOps extends TastyKernel { self: TastyUniverse =>
}
}

def mkTypeRef(tpe: Type, name: TastyName, isTerm: Boolean): Type = {
private def selectSymFromSig0(qualType: Type, name: Name, sig: Signature[Type])(implicit ctx: Context): Either[String,(Int, Symbol)] =
selectSymFromSig(qualType, name, sig).toRight(s"No matching overload of $qualType.$name with signature ${sig.show}")

private def reportThenErrorTpe(msg: String): Type = {
reporter.error(noPosition, msg)
errorType
}

def mkTypeRef(tpe: Type, name: TastyName, selectingTerm: Boolean)(implicit ctx: Context): Type = {
import NameOps._
val encoded = name.toEncodedTermName
val member = tpe.member(if (isTerm) encoded else encoded.toTypeName)
val sym = if (name.isModuleName) member.linkedClassOfClass else member
NamedType(tpe, sym)
val encoded = name.toEncodedTermName
val selector = if (selectingTerm) encoded else encoded.toTypeName
def debugSelectedSym(sym: Symbol): Symbol = {
ctx.log(s"selected ${showSym(sym)} : ${sym.tpe}")
sym
}
val resolved = name match {
case SignedName(qual, sig) =>
selectSymFromSig0(tpe, selector, sig.map(erasedNameToErasedType)).map(pair => debugSelectedSym(pair._2))
case _ => Right(tpe.member(selector))
}
val tpeOrErr = resolved.map(sym => NamedType(tpe, if (name.isModuleName) sym.linkedClassOfClass else sym))
tpeOrErr.fold(reportThenErrorTpe, identity)
}

def selectFromSig(qualType: Type, name: Name, sig: Signature[Type])(implicit ctx: Context): Type = {
val tpeOrErr = selectSymFromSig0(qualType, name, sig).map {
case (tyParamCount, sym) =>
var tpe = sym.tpe
if (name === nme.CONSTRUCTOR && tyParamCount > 0) tpe = mkPolyType(sym.owner.typeParams, tpe)
ctx.log(s"selected ${showSym(sym)} : $tpe")
tpe
}
tpeOrErr.fold(reportThenErrorTpe, identity)
}

abstract class LambdaTypeCompanion[N <: Name, PInfo <: Type, LT <: LambdaType] {
Expand Down
1 change: 1 addition & 0 deletions test/tasty/run/src-2/tastytest/TestHello.scala
Expand Up @@ -16,6 +16,7 @@ object TestHello extends Suite("TestHello") {
test(assert(HelloWorld.func1(33) === 33))
test(assert((HelloWorld.lzy: "lazy") === "lazy"))
test(assert(HelloWorld.acceptsOnlyMsg3(HelloWorld.msg3) === "Hello, World!Hello, World!"))
test(assert(HelloWorld.withArgAnnot("arg") === ("arg" : Any)))
// test(assert(HelloWorld.`<init>` === 157)) // wait until https://github.com/lampepfl/dotty/issues/7799

}
6 changes: 6 additions & 0 deletions test/tasty/run/src-3/tastytest/HelloWorld.scala
@@ -1,6 +1,11 @@
package tastytest

import scala.annotation.StaticAnnotation

object HelloWorld {

class argAnnot(arg: Any) extends StaticAnnotation

val msg1: String = "Hello, World!"
def msg2: String = "Hello, World!"
final val msg3 = "Hello, World!"
Expand All @@ -16,5 +21,6 @@ object HelloWorld {
def func1[A]: A => A = x => x
def acceptsOnlyMsg3(m: msg3.type): String = m + m
final lazy val lzy = "lazy"
def withArgAnnot(arg: Any @argAnnot(??? : Int)): Any = arg
// def `<init>`: Int = 157 // broken in https://github.com/lampepfl/dotty/issues/7799
}

0 comments on commit 14cd342

Please sign in to comment.