Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TASTy reader: add support for Scala 3.0.0-M2 #9357

Merged
merged 2 commits into from Dec 4, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions project/DottySupport.scala
Expand Up @@ -12,8 +12,8 @@ import sbt.librarymanagement.{
* Settings to support validation of TastyUnpickler against the release of dotty with the matching TASTy version
*/
object TastySupport {
val supportedTASTyRelease = "3.0.0-M1-bin-20201026-ac4e29d-NIGHTLY" // TASTy version 24
val scala3Compiler = "org.scala-lang" % "scala3-compiler_3.0.0-M1" % supportedTASTyRelease
val supportedTASTyRelease = "3.0.0-M2" // TASTy version 25.1
val scala3Compiler = "org.scala-lang" % "scala3-compiler_3.0.0-M2" % supportedTASTyRelease
}

/** Settings needed to compile with Dotty,
Expand Down
19 changes: 13 additions & 6 deletions src/compiler/scala/tools/nsc/tasty/TastyUnpickler.scala
Expand Up @@ -41,7 +41,7 @@ object TastyUnpickler {
val unpickler = new TastyUnpickler[tasty.type](new TastyReader(bytes))(tasty)
unpickler.readHeader()
unpickler.readNames()
val Some(astReader) = unpickler.readSection("ASTs"): @unchecked
val Some(astReader) = unpickler.readSection(TastyFormat.ASTsSection): @unchecked
val treeUnpickler = new TreeUnpickler[tasty.type](astReader, unpickler.nameAtRef)(tasty)
treeUnpickler.enterTopLevel(classRoot, objectRoot)
}
Expand Down Expand Up @@ -84,6 +84,12 @@ private class TastyUnpickler[Tasty <: TastyUniverse](reader: TastyReader)(implic
ctx.log(s"${nameTable.size}: ${name.debug}")
name
}
def readSignedRest(original: TastyName, target: TastyName): TastyName = {
val result = ErasedTypeRef(readName())
val paramsSig = until(end)(readParamSig())
val sig = Signature(paramsSig, result)
debugName(SignedName(original, sig, target))
}
val result = tag match {
case UTF8 =>
goto(end)
Expand All @@ -103,12 +109,13 @@ private class TastyUnpickler[Tasty <: TastyUniverse](reader: TastyReader)(implic
debugName(UniqueName(original, separator, num))
case DEFAULTGETTER =>
debugName(DefaultName(readName(), readNat()))
case TARGETSIGNED =>
val original = readName()
val target = readName()
readSignedRest(original, target)
case SIGNED =>
val original = readName()
val result = ErasedTypeRef(readName())
val paramsSig = until(end)(readParamSig())
val sig = Signature(paramsSig, result)
debugName(SignedName(original, sig))
val original = readName()
readSignedRest(original, original)
case OBJECTCLASS =>
debugName(ObjectName(readName()))
case BODYRETAINER =>
Expand Down
11 changes: 6 additions & 5 deletions src/compiler/scala/tools/nsc/tasty/TreeUnpickler.scala
Expand Up @@ -347,7 +347,7 @@ class TreeUnpickler[Tasty <: TastyUniverse](
case ANDtype => defn.IntersectionType(readType(), readType())
case ORtype => unionIsUnsupported
case SUPERtype => defn.SuperType(readType(), readType())
case MATCHtype => matchTypeIsUnsupported
case MATCHtype | MATCHCASEtype => matchTypeIsUnsupported
case POLYtype => readMethodic(Function.const(PolyType), _.toTypeName)
case METHODtype =>
def companion(mods0: TastyFlagSet) = {
Expand Down Expand Up @@ -579,7 +579,8 @@ class TreeUnpickler[Tasty <: TastyUniverse](
case STATIC => addFlag(Static)
case OBJECT => addFlag(Object)
case TRAIT => addFlag(Trait)
case SUPERTRAIT => addFlag(SuperTrait)
case TRANSPARENT => addFlag(Transparent)
case INFIX => addFlag(Infix)
case ENUM => addFlag(Enum)
case LOCAL => addFlag(Local)
case SYNTHETIC => addFlag(Synthetic)
Expand Down Expand Up @@ -720,7 +721,7 @@ class TreeUnpickler[Tasty <: TastyUniverse](
tag match {
case DEFDEF =>
val isMacro = repr.originalFlagSet.is(Erased | Macro)
checkUnsupportedFlags(repr.tastyOnlyFlags &~ (Extension | Exported | optFlag(isMacro)(Erased)))
checkUnsupportedFlags(repr.tastyOnlyFlags &~ (Extension | Exported | Infix | optFlag(isMacro)(Erased)))
val isCtor = sym.isConstructor
val typeParams = {
if (isCtor) {
Expand Down Expand Up @@ -767,8 +768,8 @@ class TreeUnpickler[Tasty <: TastyUniverse](
else tpe
)
case TYPEDEF | TYPEPARAM =>
val allowedTypeFlags = Enum | Open | Exported | SuperTrait
val allowedClassFlags = allowedTypeFlags | Opaque
val allowedTypeFlags = Enum | Open | Exported | Infix
val allowedClassFlags = allowedTypeFlags | Opaque | Transparent
if (sym.isClass) {
checkUnsupportedFlags(repr.tastyOnlyFlags &~ allowedClassFlags)
sym.owner.ensureCompleted()
Expand Down
Expand Up @@ -50,7 +50,7 @@ trait AnnotationOps { self: TastyUniverse =>
ctx.log(s"annotation on $annotee: $atree")
val annot = mkAnnotation(atree)
val annotSym = annot.tpe.typeSymbol
if ((annotSym eq defn.AlphaAnnotationClass) || (annotSym eq defn.StaticMethodAnnotationClass)) {
if ((annotSym eq defn.TargetNameAnnotationClass) || (annotSym eq defn.StaticMethodAnnotationClass)) {
annotee.addAnnotation(
u.definitions.CompileTimeOnlyAttr,
u.Literal(u.Constant(unsupportedMessage(s"annotation on $annotee: @$annot"))))
Expand Down
35 changes: 18 additions & 17 deletions src/compiler/scala/tools/nsc/tasty/bridge/FlagOps.scala
Expand Up @@ -24,7 +24,7 @@ trait FlagOps { self: TastyUniverse =>

object FlagSets {
val TastyOnlyFlags: TastyFlagSet = (
Erased | Internal | Inline | InlineProxy | Opaque | Extension | Given | Exported | SuperTrait | Enum
Erased | Internal | Inline | InlineProxy | Opaque | Extension | Given | Exported | Transparent | Enum | Infix
| Open | ParamAlias
)
val TermParamOrAccessor: TastyFlagSet = Param | ParamSetter
Expand Down Expand Up @@ -75,21 +75,22 @@ trait FlagOps { self: TastyUniverse =>
def showTasty(flags: TastyFlagSet): String = { // keep up to date with with FlagSets.TastyOnlyFlags
val tflags = flags & FlagSets.TastyOnlyFlags
if (!tflags) "EmptyTastyFlags"
else (tflags).toSingletonSets.map { f =>
(f: @unchecked) match {
case Erased => "erased"
case Internal => "<internal>"
case Inline => "inline"
case InlineProxy => "<inlineproxy>"
case Opaque => "opaque"
case Extension => "<extension>"
case Given => "given"
case Exported => "<exported>"
case SuperTrait => "<supertrait>"
case Enum => "enum"
case Open => "open"
case ParamAlias => "<paramalias>"
}
} mkString(" | ")
else {
val sb = collection.mutable.ArrayBuffer.empty[String]
if (flags.is(Erased)) sb += "erased"
if (flags.is(Internal)) sb += "<internal>"
if (flags.is(Inline)) sb += "inline"
if (flags.is(InlineProxy)) sb += "<inlineproxy>"
if (flags.is(Opaque)) sb += "opaque"
if (flags.is(Extension)) sb += "<extension>"
if (flags.is(Given)) sb += "given"
if (flags.is(Exported)) sb += "<exported>"
if (flags.is(Transparent)) sb += "transparent"
if (flags.is(Enum)) sb += "enum"
if (flags.is(Open)) sb += "open"
if (flags.is(ParamAlias)) sb += "<paramalias>"
if (flags.is(Infix)) sb += "infix"
sb.mkString(" | ")
}
}
}
65 changes: 35 additions & 30 deletions src/compiler/scala/tools/nsc/tasty/bridge/SymbolOps.scala
Expand Up @@ -93,8 +93,8 @@ trait SymbolOps { self: TastyUniverse =>
termParamss

def namedMemberOfType(space: Type, tname: TastyName)(implicit ctx: Context): Symbol = tname match {
case SignedName(qual, sig) => signedMemberOfSpace(space, qual, sig.map(_.encode))
case _ => memberOfSpace(space, tname)
case SignedName(qual, sig, target) => signedMemberOfSpace(space, qual, sig.map(_.encode), target)
case _ => memberOfSpace(space, tname)
}

private def memberOfSpace(space: Type, tname: TastyName)(implicit ctx: Context): Symbol = {
Expand Down Expand Up @@ -145,37 +145,42 @@ trait SymbolOps { self: TastyUniverse =>
typeError(s"can't find $missing; perhaps it is missing from the classpath.")
}

private def signedMemberOfSpace(space: Type, qual: TastyName, sig: MethodSignature[ErasedTypeRef])(implicit ctx: Context): Symbol = {
ctx.log(s"""<<< looking for overload in symbolOf[$space] @@ $qual: ${showSig(sig)}""")
val member = space.member(encodeTermName(qual))
if (!(isSymbol(member) && hasType(member))) errorMissing(space, qual)
val (tyParamCount, argTpeRefs) = {
val (tyParamCounts, params) = sig.params.partitionMap(identity)
if (tyParamCounts.length > 1) {
unsupportedError(s"multiple type parameter lists on erased method signature ${showSig(sig)}")
}
(tyParamCounts.headOption.getOrElse(0), params)
private def signedMemberOfSpace(space: Type, qual: TastyName, sig: MethodSignature[ErasedTypeRef], target: TastyName)(implicit ctx: Context): Symbol = {
if (target ne qual) {
unsupportedError(s"selection of method $qual with @targetName(" + '"' + target + '"' + ")")
}
def compareSym(sym: Symbol): Boolean = sym match {
case sym: u.MethodSymbol =>
val method = sym.tpe.asSeenFrom(space, sym.owner)
ctx.log(s">>> trying $sym: $method")
val params = method.paramss.flatten
val isJava = sym.isJavaDefined
NameErasure.sigName(method.finalResultType, isJava) === sig.result &&
params.length === argTpeRefs.length &&
(qual === TastyName.Constructor && tyParamCount === member.owner.typeParams.length
|| tyParamCount === sym.typeParams.length) &&
params.zip(argTpeRefs).forall { case (param, tpe) => NameErasure.sigName(param.tpe, isJava) === tpe } && {
ctx.log(s">>> selected ${showSym(sym)}: ${sym.tpe}")
true
else {
ctx.log(s"""<<< looking for overload in symbolOf[$space] @@ $qual: ${showSig(sig)}""")
val member = space.member(encodeTermName(qual))
if (!(isSymbol(member) && hasType(member))) errorMissing(space, qual)
val (tyParamCount, argTpeRefs) = {
val (tyParamCounts, params) = sig.params.partitionMap(identity)
if (tyParamCounts.length > 1) {
unsupportedError(s"multiple type parameter lists on erased method signature ${showSig(sig)}")
}
case _ =>
ctx.log(s"""! member[$space]("$qual") ${showSym(sym)} is not a method""")
false
(tyParamCounts.headOption.getOrElse(0), params)
}
def compareSym(sym: Symbol): Boolean = sym match {
case sym: u.MethodSymbol =>
val method = sym.tpe.asSeenFrom(space, sym.owner)
ctx.log(s">>> trying $sym: $method")
val params = method.paramss.flatten
val isJava = sym.isJavaDefined
NameErasure.sigName(method.finalResultType, isJava) === sig.result &&
params.length === argTpeRefs.length &&
(qual === TastyName.Constructor && tyParamCount === member.owner.typeParams.length
|| tyParamCount === sym.typeParams.length) &&
params.zip(argTpeRefs).forall { case (param, tpe) => NameErasure.sigName(param.tpe, isJava) === tpe } && {
ctx.log(s">>> selected ${showSym(sym)}: ${sym.tpe}")
true
}
case _ =>
ctx.log(s"""! member[$space]("$qual") ${showSym(sym)} is not a method""")
false
}
member.asTerm.alternatives.find(compareSym).getOrElse(
typeError(s"No matching overload of $space.$qual with signature ${showSig(sig)}"))
}
member.asTerm.alternatives.find(compareSym).getOrElse(
typeError(s"No matching overload of $space.$qual with signature ${showSig(sig)}"))
}

def showSig(sig: MethodSignature[ErasedTypeRef]): String = sig.map(_.signature).show
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/scala/tools/nsc/tasty/bridge/TypeOps.scala
Expand Up @@ -77,7 +77,7 @@ trait TypeOps { self: TastyUniverse =>

final val ChildAnnot: Symbol = u.definitions.ChildAnnotationClass
final val RepeatedAnnot: Symbol = u.definitions.RepeatedAnnotationClass
final val AlphaAnnotationClass: Symbol = u.definitions.AlphaAnnotationClass
final val TargetNameAnnotationClass: Symbol = u.definitions.TargetNameAnnotationClass
final val StaticMethodAnnotationClass: Symbol = u.definitions.StaticMethodAnnotationClass

object PolyFunctionType {
Expand Down
93 changes: 46 additions & 47 deletions src/compiler/scala/tools/tasty/TastyFlags.scala
Expand Up @@ -55,10 +55,11 @@ object TastyFlags {
final val Given = Extension.next
final val Exported = Given.next
final val Macro = Exported.next
final val SuperTrait = Macro.next
final val Enum = SuperTrait.next
final val Transparent = Macro.next
final val Enum = Transparent.next
final val Open = Enum.next
final val ParamAlias = Open.next
final val Infix = ParamAlias.next

private[TastyFlags] final val maxFlag: Long = ParamAlias.shift

Expand All @@ -80,7 +81,6 @@ object TastyFlags {
TastyFlagSet(1L << shift)
}

def toSingletonSets: SingletonSets = SingletonSets(toLong)
def |(other: TastyFlagSet): TastyFlagSet = TastyFlagSet(toLong | other.toLong)
def &(mask: TastyFlagSet): TastyFlagSet = TastyFlagSet(toLong & mask.toLong)
def &~(mask: TastyFlagSet): TastyFlagSet = TastyFlagSet(toLong & ~mask.toLong)
Expand All @@ -96,50 +96,49 @@ object TastyFlags {
"EmptyTastyFlags"
}
else {
toSingletonSets.map { f =>
(f: @unchecked) match {
case Private => "Private"
case Protected => "Protected"
case AbsOverride => "AbsOverride"
case Abstract => "Abstract"
case Final => "Final"
case Sealed => "Sealed"
case Case => "Case"
case Implicit => "Implicit"
case Lazy => "Lazy"
case Override => "Override"
case Static => "Static"
case Object => "Object"
case Trait => "Trait"
case Local => "Local"
case Synthetic => "Synthetic"
case Artifact => "Artifact"
case Mutable => "Mutable"
case FieldAccessor => "FieldAccessor"
case CaseAccessor => "CaseAccessor"
case Covariant => "Covariant"
case Contravariant => "Contravariant"
case HasDefault => "HasDefault"
case Stable => "Stable"
case ParamSetter => "ParamSetter"
case Param => "Param"
case Deferred => "Deferred"
case Method => "Method"
case Erased => "Erased"
case Internal => "Internal"
case Inline => "Inline"
case InlineProxy => "InlineProxy"
case Opaque => "Opaque"
case Extension => "Extension"
case Given => "Given"
case Exported => "Exported"
case Macro => "Macro"
case SuperTrait => "SuperTrait"
case Enum => "Enum"
case Open => "Open"
case ParamAlias => "ParamAlias"
}
} mkString(" | ")
val sb = collection.mutable.ArrayBuffer.empty[String]
if (is(Private)) sb += "Private"
if (is(Protected)) sb += "Protected"
if (is(AbsOverride)) sb += "AbsOverride"
if (is(Abstract)) sb += "Abstract"
if (is(Final)) sb += "Final"
if (is(Sealed)) sb += "Sealed"
if (is(Case)) sb += "Case"
if (is(Implicit)) sb += "Implicit"
if (is(Lazy)) sb += "Lazy"
if (is(Override)) sb += "Override"
if (is(Static)) sb += "Static"
if (is(Object)) sb += "Object"
if (is(Trait)) sb += "Trait"
if (is(Local)) sb += "Local"
if (is(Synthetic)) sb += "Synthetic"
if (is(Artifact)) sb += "Artifact"
if (is(Mutable)) sb += "Mutable"
if (is(FieldAccessor)) sb += "FieldAccessor"
if (is(CaseAccessor)) sb += "CaseAccessor"
if (is(Covariant)) sb += "Covariant"
if (is(Contravariant)) sb += "Contravariant"
if (is(HasDefault)) sb += "HasDefault"
if (is(Stable)) sb += "Stable"
if (is(ParamSetter)) sb += "ParamSetter"
if (is(Param)) sb += "Param"
if (is(Deferred)) sb += "Deferred"
if (is(Method)) sb += "Method"
if (is(Erased)) sb += "Erased"
if (is(Internal)) sb += "Internal"
if (is(Inline)) sb += "Inline"
if (is(InlineProxy)) sb += "InlineProxy"
if (is(Opaque)) sb += "Opaque"
if (is(Extension)) sb += "Extension"
if (is(Given)) sb += "Given"
if (is(Exported)) sb += "Exported"
if (is(Macro)) sb += "Macro"
if (is(Transparent)) sb += "Transparent"
if (is(Enum)) sb += "Enum"
if (is(Open)) sb += "Open"
if (is(ParamAlias)) sb += "ParamAlias"
if (is(Infix)) sb += "Infix"
sb.mkString(" | ")
}
}
}
Expand Down