diff --git a/project/DottySupport.scala b/project/DottySupport.scala index 44e2c913b6f0..00eb3f0ffd06 100644 --- a/project/DottySupport.scala +++ b/project/DottySupport.scala @@ -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, diff --git a/src/compiler/scala/tools/nsc/tasty/TastyUnpickler.scala b/src/compiler/scala/tools/nsc/tasty/TastyUnpickler.scala index 86e297bebb9e..cb3d81563f4e 100644 --- a/src/compiler/scala/tools/nsc/tasty/TastyUnpickler.scala +++ b/src/compiler/scala/tools/nsc/tasty/TastyUnpickler.scala @@ -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) } @@ -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) @@ -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 => diff --git a/src/compiler/scala/tools/nsc/tasty/TreeUnpickler.scala b/src/compiler/scala/tools/nsc/tasty/TreeUnpickler.scala index e0ebc041499e..87ad7fdec542 100644 --- a/src/compiler/scala/tools/nsc/tasty/TreeUnpickler.scala +++ b/src/compiler/scala/tools/nsc/tasty/TreeUnpickler.scala @@ -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) = { @@ -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) @@ -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) { @@ -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() diff --git a/src/compiler/scala/tools/nsc/tasty/bridge/AnnotationOps.scala b/src/compiler/scala/tools/nsc/tasty/bridge/AnnotationOps.scala index b3d347f8e901..948bbc2868e7 100644 --- a/src/compiler/scala/tools/nsc/tasty/bridge/AnnotationOps.scala +++ b/src/compiler/scala/tools/nsc/tasty/bridge/AnnotationOps.scala @@ -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")))) diff --git a/src/compiler/scala/tools/nsc/tasty/bridge/FlagOps.scala b/src/compiler/scala/tools/nsc/tasty/bridge/FlagOps.scala index 7e4dd02a9831..b4f88b88c886 100644 --- a/src/compiler/scala/tools/nsc/tasty/bridge/FlagOps.scala +++ b/src/compiler/scala/tools/nsc/tasty/bridge/FlagOps.scala @@ -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 @@ -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 => "" - case Inline => "inline" - case InlineProxy => "" - case Opaque => "opaque" - case Extension => "" - case Given => "given" - case Exported => "" - case SuperTrait => "" - case Enum => "enum" - case Open => "open" - case ParamAlias => "" - } - } mkString(" | ") + else { + val sb = collection.mutable.ArrayBuffer.empty[String] + if (flags.is(Erased)) sb += "erased" + if (flags.is(Internal)) sb += "" + if (flags.is(Inline)) sb += "inline" + if (flags.is(InlineProxy)) sb += "" + if (flags.is(Opaque)) sb += "opaque" + if (flags.is(Extension)) sb += "" + if (flags.is(Given)) sb += "given" + if (flags.is(Exported)) sb += "" + if (flags.is(Transparent)) sb += "transparent" + if (flags.is(Enum)) sb += "enum" + if (flags.is(Open)) sb += "open" + if (flags.is(ParamAlias)) sb += "" + if (flags.is(Infix)) sb += "infix" + sb.mkString(" | ") + } } } diff --git a/src/compiler/scala/tools/nsc/tasty/bridge/SymbolOps.scala b/src/compiler/scala/tools/nsc/tasty/bridge/SymbolOps.scala index 42c71ad48605..83213a91a639 100644 --- a/src/compiler/scala/tools/nsc/tasty/bridge/SymbolOps.scala +++ b/src/compiler/scala/tools/nsc/tasty/bridge/SymbolOps.scala @@ -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 = { @@ -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 diff --git a/src/compiler/scala/tools/nsc/tasty/bridge/TypeOps.scala b/src/compiler/scala/tools/nsc/tasty/bridge/TypeOps.scala index c5ef2a36129f..9dfdd5c5b092 100644 --- a/src/compiler/scala/tools/nsc/tasty/bridge/TypeOps.scala +++ b/src/compiler/scala/tools/nsc/tasty/bridge/TypeOps.scala @@ -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 { diff --git a/src/compiler/scala/tools/tasty/TastyFlags.scala b/src/compiler/scala/tools/tasty/TastyFlags.scala index 7cf0eeef9aba..0041a3e3f632 100644 --- a/src/compiler/scala/tools/tasty/TastyFlags.scala +++ b/src/compiler/scala/tools/tasty/TastyFlags.scala @@ -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 @@ -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) @@ -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(" | ") } } } diff --git a/src/compiler/scala/tools/tasty/TastyFormat.scala b/src/compiler/scala/tools/tasty/TastyFormat.scala index 39b792375b47..2343f958ecde 100644 --- a/src/compiler/scala/tools/tasty/TastyFormat.scala +++ b/src/compiler/scala/tools/tasty/TastyFormat.scala @@ -15,8 +15,12 @@ package scala.tools.tasty object TastyFormat { final val header: Array[Int] = Array(0x5C, 0xA1, 0xAB, 0x1F) - val MajorVersion: Int = 24 - val MinorVersion: Int = 0 + val MajorVersion: Int = 25 + val MinorVersion: Int = 1 + + final val ASTsSection = "ASTs" + final val PositionsSection = "Positions" + final val CommentsSection = "Comments" /** Tags used to serialize names */ class NameTags { @@ -45,6 +49,9 @@ object TastyFormat { final val OBJECTCLASS = 23 // The name of an object class (or: module class) `$`. + final val TARGETSIGNED = 62 // A triple of a name, a targetname and a signature, used to identify + // possibly overloaded methods that carry a @targetName annotation. + final val SIGNED = 63 // A pair of a name and a signature, used to identify // possibly overloaded methods. } @@ -98,7 +105,8 @@ object TastyFormat { final val OPEN = 40 final val PARAMEND = 41 final val PARAMalias = 42 - final val SUPERTRAIT = 43 + final val TRANSPARENT = 43 + final val INFIX = 44 // Cat. 2: tag Nat @@ -202,6 +210,7 @@ object TastyFormat { final val MATCHtype = 190 final val MATCHtpt = 191 + final val MATCHCASEtype = 192 final val HOLE = 255 @@ -212,7 +221,7 @@ object TastyFormat { /** Useful for debugging */ def isLegalTag(tag: Int): Boolean = - firstSimpleTreeTag <= tag && tag <= SUPERTRAIT || + firstSimpleTreeTag <= tag && tag <= INFIX || firstNatTreeTag <= tag && tag <= RENAMED || firstASTTreeTag <= tag && tag <= BOUNDED || firstNatASTTreeTag <= tag && tag <= NAMEDARG || @@ -241,7 +250,8 @@ object TastyFormat { | STATIC | OBJECT | TRAIT - | SUPERTRAIT + | TRANSPARENT + | INFIX | ENUM | LOCAL | SYNTHETIC @@ -303,7 +313,8 @@ object TastyFormat { case OBJECT => "OBJECT" case TRAIT => "TRAIT" case ENUM => "ENUM" - case SUPERTRAIT => "SUPERTRAIT" + case TRANSPARENT => "TRANSPARENT" + case INFIX => "INFIX" case LOCAL => "LOCAL" case SYNTHETIC => "SYNTHETIC" case ARTIFACT => "ARTIFACT" @@ -409,6 +420,7 @@ object TastyFormat { case TYPELAMBDAtype => "TYPELAMBDAtype" case LAMBDAtpt => "LAMBDAtpt" case MATCHtype => "MATCHtype" + case MATCHCASEtype => "MATCHCASEtype" case MATCHtpt => "MATCHtpt" case PARAMtype => "PARAMtype" case ANNOTATION => "ANNOTATION" diff --git a/src/compiler/scala/tools/tasty/TastyName.scala b/src/compiler/scala/tools/tasty/TastyName.scala index e99eff05bcdc..e69e42b33c1c 100644 --- a/src/compiler/scala/tools/tasty/TastyName.scala +++ b/src/compiler/scala/tools/tasty/TastyName.scala @@ -21,12 +21,15 @@ object TastyName { final case class SimpleName(raw: String) extends TastyName final case class ObjectName(base: TastyName) extends TastyName final case class QualifiedName(qual: TastyName, sep: SimpleName, selector: SimpleName) extends TastyName - final case class SignedName(qual: TastyName, sig: Signature.MethodSignature[ErasedTypeRef]) extends TastyName final case class UniqueName(qual: TastyName, sep: SimpleName, num: Int) extends TastyName final case class DefaultName(qual: TastyName, num: Int) extends TastyName final case class PrefixName(prefix: SimpleName, qual: TastyName) extends TastyName final case class SuffixName(qual: TastyName, suffix: SimpleName) extends TastyName final case class TypeName private (base: TastyName) extends TastyName + final case class SignedName( + qual: TastyName, + sig: Signature.MethodSignature[ErasedTypeRef], + target: TastyName) extends TastyName object TypeName { private[TastyName] def apply(base: TastyName): TypeName = base match { @@ -105,13 +108,13 @@ object TastyName { def traverse(sb: StringBuilder, name: TastyName): StringBuilder = name match { - case SimpleName(raw) => sb append raw - case DefaultName(qual, num) => traverse(sb, qual) append "[Default " append (num + 1) append ']' - case PrefixName(prefix, qual) => traverse(sb, qual) append "[Prefix " append (prefix.raw) append ']' - case SuffixName(qual, suffix) => traverse(sb, qual) append "[Suffix " append (suffix.raw) append ']' - case ObjectName(name) => traverse(sb, name) append "[ModuleClass]" - case TypeName(name) => traverse(sb, name) append "[Type]" - case SignedName(name,sig) => merge(traverse(sb, name) append "[Signed ", sig.map(_.signature)) append ']' + case SimpleName(raw) => sb append raw + case DefaultName(qual, num) => traverse(sb, qual) append "[Default " append (num + 1) append ']' + case PrefixName(prefix, qual) => traverse(sb, qual) append "[Prefix " append (prefix.raw) append ']' + case SuffixName(qual, suffix) => traverse(sb, qual) append "[Suffix " append (suffix.raw) append ']' + case ObjectName(name) => traverse(sb, name) append "[ModuleClass]" + case TypeName(name) => traverse(sb, name) append "[Type]" + case SignedName(name, sig, target) => merge(traverse(sb, name) append "[Signed ", sig.map(_.signature)) append " @" append target.source append ']' case QualifiedName(qual, sep, name) => traverse(sb, qual) append "[Qualified " append (sep.raw) append ' ' append (name.raw) append ']' @@ -160,7 +163,7 @@ object TastyName { case PrefixName(prefix, qual) => PrefixName(prefix, deepEncode(qual)) case SuffixName(qual, suffix) => SuffixName(deepEncode(qual), suffix) case TypeName(base) => TypeName(deepEncode(base)) - case SignedName(qual, sig) => SignedName(deepEncode(qual), sig.map(_.encode)) + case SignedName(qual, sig, target) => SignedName(deepEncode(qual), sig.map(_.encode), target) } } @@ -208,13 +211,13 @@ sealed abstract class TastyName extends Product with Serializable { self => final def toTypeName: TypeName = TypeName(self) final def stripSignedPart: TastyName = self match { - case SignedName(pre, _) => pre - case name => name + case SignedName(pre, _, _) => pre + case name => name } final def isSignedConstructor = self match { - case SignedName(TastyName.Constructor, sig) if isMethodSignature(sig) => true - case _ => false + case SignedName(TastyName.Constructor, sig, _) if isMethodSignature(sig) => true + case _ => false } /** Guard against API change to SignedName */ diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala index e278798e4373..be0e8c057531 100644 --- a/src/reflect/scala/reflect/internal/Definitions.scala +++ b/src/reflect/scala/reflect/internal/Definitions.scala @@ -1315,7 +1315,7 @@ trait Definitions extends api.StandardDefinitions { // Tasty Unpickling Helpers - only access when Scala 3 library is expected to be available lazy val ChildAnnotationClass = getClassIfDefined("scala.annotation.internal.Child") lazy val RepeatedAnnotationClass = getClassIfDefined("scala.annotation.internal.Repeated") - lazy val AlphaAnnotationClass = getClassIfDefined("scala.annotation.alpha") + lazy val TargetNameAnnotationClass = getClassIfDefined("scala.annotation.targetName") lazy val StaticMethodAnnotationClass = getClassIfDefined("scala.annotation.static") lazy val PolyFunctionClass = getClassIfDefined("scala.PolyFunction") diff --git a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala index f34b1b9f6e4b..be33ed5a6651 100644 --- a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala +++ b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala @@ -435,7 +435,7 @@ trait JavaUniverseForce { self: runtime.JavaUniverse => definitions.uncheckedVarianceClass definitions.ChildAnnotationClass definitions.RepeatedAnnotationClass - definitions.AlphaAnnotationClass + definitions.TargetNameAnnotationClass definitions.StaticMethodAnnotationClass definitions.PolyFunctionClass definitions.BeanPropertyAttr diff --git a/test/tasty/neg-move-macros/src-3/MacroCompat.scala b/test/tasty/neg-move-macros/src-3/MacroCompat.scala index 84d1e1e96707..d3c3374b17c3 100644 --- a/test/tasty/neg-move-macros/src-3/MacroCompat.scala +++ b/test/tasty/neg-move-macros/src-3/MacroCompat.scala @@ -13,10 +13,11 @@ object MacroCompat { object Macros3 { import quoted._ - def posImpl(using qctx: QuoteContext): Expr[Position] = { - import qctx.reflect.given - val name = qctx.reflect.rootPosition.sourceFile.jpath.getFileName.toString - val line = qctx.reflect.rootPosition.startLine + 1 + def posImpl(using quotes: Quotes): Expr[Position] = { + import quotes.reflect.given + val pos = quotes.reflect.Position.ofMacroExpansion + val name = pos.sourceFile.jpath.getFileName.toString + val line = pos.startLine + 1 '{ Position(${Expr(name)}, ${Expr(line)}) } } } diff --git a/test/tasty/neg/src-2/TestAlphaAnnot.check b/test/tasty/neg/src-2/TestAlphaAnnot.check deleted file mode 100644 index d9a7d1e3690e..000000000000 --- a/test/tasty/neg/src-2/TestAlphaAnnot.check +++ /dev/null @@ -1,4 +0,0 @@ -TestAlphaAnnot_fail.scala:4: error: Unsupported Scala 3 annotation on method ++: @scala.annotation.alpha("doubleplus"); found in object tastytest.AlphaAnnot. - def test1 = AlphaAnnot.++ // error - ^ -1 error diff --git a/test/tasty/neg/src-2/TestAlphaAnnot_fail.scala b/test/tasty/neg/src-2/TestAlphaAnnot_fail.scala deleted file mode 100644 index 58c9020a4407..000000000000 --- a/test/tasty/neg/src-2/TestAlphaAnnot_fail.scala +++ /dev/null @@ -1,6 +0,0 @@ -package tastytest - -object TestAlphaAnnot { - def test1 = AlphaAnnot.++ // error - def test2 = AlphaAnnot.foo // ok -} diff --git a/test/tasty/neg/src-2/TestCompiletimeQuoteType.check b/test/tasty/neg/src-2/TestCompiletimeQuoteType.check index 3a1df5e06ca5..c041a36c4d04 100644 --- a/test/tasty/neg/src-2/TestCompiletimeQuoteType.check +++ b/test/tasty/neg/src-2/TestCompiletimeQuoteType.check @@ -1,4 +1,4 @@ -TestCompiletimeQuoteType_fail.scala:4: error: Unsupported Scala 3 context function type in result: scala.quoted.QuoteContext ?=> scala.quoted.Type[T]; found in method apply in object scala.quoted.Type. +TestCompiletimeQuoteType_fail.scala:4: error: Unsupported Scala 3 context function type in result: scala.quoted.Quotes ?=> scala.quoted.Type[T]; found in method of in object scala.quoted.Type. def test = CompiletimeQuoteType.f[Int] ^ 1 error diff --git a/test/tasty/neg/src-2/TestIntent.check b/test/tasty/neg/src-2/TestIntent.check index 61f56fb981a6..6127184eddb4 100644 --- a/test/tasty/neg/src-2/TestIntent.check +++ b/test/tasty/neg/src-2/TestIntent.check @@ -1,7 +1,7 @@ TestIntent_fail.scala:6: error: Unsupported Scala 3 inline macro method here; found in object tastytest.intent.Position. - extension_apply("3 + 3") { - ^ + apply("3 + 3") { + ^ TestIntent_fail.scala:7: error: could not find implicit value for parameter pos: tastytest.intent.Position - extension_in("should be 6")(extension_toEqual(expect(3 + 3))(6)) - ^ + in("should be 6")(toEqual(expect(3 + 3))(6)) + ^ 2 errors diff --git a/test/tasty/neg/src-2/TestIntent_fail.scala b/test/tasty/neg/src-2/TestIntent_fail.scala index 241a851699fe..17bdb2f50a3c 100644 --- a/test/tasty/neg/src-2/TestIntent_fail.scala +++ b/test/tasty/neg/src-2/TestIntent_fail.scala @@ -3,7 +3,7 @@ package tastytest import intent._ class TestIntent extends TestSuite with Stateless { - extension_apply("3 + 3") { - extension_in("should be 6")(extension_toEqual(expect(3 + 3))(6)) + apply("3 + 3") { + in("should be 6")(toEqual(expect(3 + 3))(6)) } } diff --git a/test/tasty/neg/src-2/TestSelectWithTarget.check b/test/tasty/neg/src-2/TestSelectWithTarget.check new file mode 100644 index 000000000000..60ca319eaaf9 --- /dev/null +++ b/test/tasty/neg/src-2/TestSelectWithTarget.check @@ -0,0 +1,4 @@ +TestSelectWithTarget_fail.scala:10: error: Unsupported Scala 3 selection of method foo with @targetName("fooString"); found in method selectFooString in object tastytest.SelectWithTarget. + def test = SelectWithTarget.selectFooString + ^ +1 error diff --git a/test/tasty/neg/src-2/TestSelectWithTarget_fail.scala b/test/tasty/neg/src-2/TestSelectWithTarget_fail.scala new file mode 100644 index 000000000000..48df0224770e --- /dev/null +++ b/test/tasty/neg/src-2/TestSelectWithTarget_fail.scala @@ -0,0 +1,12 @@ +package tastytest + +object TestSelectWithTarget { + + // We error when an annotation selects a + // method overloaded with a targetAnnot + // until we can erase them correctly. + // e.g. the annotation arguments may be + // reflected by a macro into real trees + def test = SelectWithTarget.selectFooString + +} diff --git a/test/tasty/neg/src-2/TestTargetNameAnnot.check b/test/tasty/neg/src-2/TestTargetNameAnnot.check new file mode 100644 index 000000000000..9d2e9adcd844 --- /dev/null +++ b/test/tasty/neg/src-2/TestTargetNameAnnot.check @@ -0,0 +1,4 @@ +TestTargetNameAnnot_fail.scala:4: error: Unsupported Scala 3 annotation on method ++: @scala.annotation.targetName("doubleplus"); found in object tastytest.TargetNameAnnot. + def test1 = TargetNameAnnot.++ // error + ^ +1 error diff --git a/test/tasty/neg/src-2/TestTargetNameAnnot_fail.scala b/test/tasty/neg/src-2/TestTargetNameAnnot_fail.scala new file mode 100644 index 000000000000..41aa3be0ab59 --- /dev/null +++ b/test/tasty/neg/src-2/TestTargetNameAnnot_fail.scala @@ -0,0 +1,6 @@ +package tastytest + +object TestTargetNameAnnot { + def test1 = TargetNameAnnot.++ // error + def test2 = TargetNameAnnot.foo // ok +} diff --git a/test/tasty/neg/src-3/AlphaAnnot.scala b/test/tasty/neg/src-3/AlphaAnnot.scala deleted file mode 100644 index 52cd2a28d47d..000000000000 --- a/test/tasty/neg/src-3/AlphaAnnot.scala +++ /dev/null @@ -1,9 +0,0 @@ -package tastytest - -object AlphaAnnot { - - @annotation.alpha("doubleplus") def ++ : Unit = println("++") - - def foo = 23 - -} diff --git a/test/tasty/neg/src-3/CompiletimeQuoteType.scala b/test/tasty/neg/src-3/CompiletimeQuoteType.scala index 8a9b16b85741..75142ec81391 100644 --- a/test/tasty/neg/src-3/CompiletimeQuoteType.scala +++ b/test/tasty/neg/src-3/CompiletimeQuoteType.scala @@ -3,7 +3,7 @@ package tastytest import scala.quoted._ object CompiletimeQuoteType { - def f[T: Type](using QuoteContext) = { + def f[T: Type](using Quotes) = { implicitly[Type[List[T]]] } } diff --git a/test/tasty/neg/src-3/SelectWithTarget.scala b/test/tasty/neg/src-3/SelectWithTarget.scala new file mode 100644 index 000000000000..42bf105ea222 --- /dev/null +++ b/test/tasty/neg/src-3/SelectWithTarget.scala @@ -0,0 +1,22 @@ +package tastytest + +import scala.annotation.{StaticAnnotation, targetName} + +object SelectWithTarget { + + class defAnnot(arg: Any) extends StaticAnnotation + + @defAnnot(Overloads.foo("hi")) + def selectFooString: Int = 23 + + object Overloads { + + @targetName("fooString") + def foo(t: => String): Int = t.length + + @targetName("fooInt") + def foo(t: => Int): Int = t + + } + +} diff --git a/test/tasty/neg/src-3/TargetNameAnnot.scala b/test/tasty/neg/src-3/TargetNameAnnot.scala new file mode 100644 index 000000000000..157fd1809548 --- /dev/null +++ b/test/tasty/neg/src-3/TargetNameAnnot.scala @@ -0,0 +1,9 @@ +package tastytest + +object TargetNameAnnot { + + @annotation.targetName("doubleplus") def ++ : Unit = println("++") + + def foo = 23 + +} diff --git a/test/tasty/neg/src-3/intent/Position.scala b/test/tasty/neg/src-3/intent/Position.scala index b57c1953e5c7..b1476624b1be 100644 --- a/test/tasty/neg/src-3/intent/Position.scala +++ b/test/tasty/neg/src-3/intent/Position.scala @@ -27,5 +27,5 @@ object Position: implicit inline def here: Position = ${ genPosition } - private def genPosition(implicit qctx: QuoteContext): Expr[Position] = + private def genPosition(implicit q: Quotes): Expr[Position] = '{ ??? } diff --git a/test/tasty/pos/src-2/tastytest/TestInfix.scala b/test/tasty/pos/src-2/tastytest/TestInfix.scala new file mode 100644 index 000000000000..da73e5f81c55 --- /dev/null +++ b/test/tasty/pos/src-2/tastytest/TestInfix.scala @@ -0,0 +1,12 @@ +package tastytest + +import Infix.BoxedInt + +object TestInfix { + + val x = BoxedInt(0) + val y = BoxedInt(2) + + def test = assert((x min y) == x) + +} diff --git a/test/tasty/pos/src-3/tastytest/Infix.scala b/test/tasty/pos/src-3/tastytest/Infix.scala new file mode 100644 index 000000000000..e3f4efc491b6 --- /dev/null +++ b/test/tasty/pos/src-3/tastytest/Infix.scala @@ -0,0 +1,13 @@ +package tastytest + +object Infix { + + final case class BoxedInt(toInt: Int) { + + infix def min (that: BoxedInt): BoxedInt = + if toInt.min(that.toInt) == toInt then this + else that + + } + +} diff --git a/test/tasty/run/src-2/tastytest/TestFunctor.scala b/test/tasty/run/src-2/tastytest/TestFunctor.scala index df91ee2e0c6d..2ef29caf4987 100644 --- a/test/tasty/run/src-2/tastytest/TestFunctor.scala +++ b/test/tasty/run/src-2/tastytest/TestFunctor.scala @@ -3,20 +3,20 @@ package tastytest object TestFunctor extends Suite("TestFunctor") { implicit object ListFunctor extends Functor[List] { - def extension_map[A, B](fa: List[A])(f: A => B): List[B] = fa.map(f) + def map[A, B](fa: List[A])(f: A => B): List[B] = fa.map(f) } implicit object ListFunctorI extends FunctorI[List] { - def extension_map[A, B](fa: List[A])(f: A => B): List[B] = fa.map(f) + def map[A, B](fa: List[A])(f: A => B): List[B] = fa.map(f) } implicit object ListFunctorL extends FunctorL[List] { - def extension_map[A, B](fa: List[A])(f: A => B): List[B] = fa.map(f) + def map[A, B](fa: List[A])(f: A => B): List[B] = fa.map(f) } - def toStringOnFunctorL[F[X] <: List[X]: FunctorL, A](fa: F[A]): F[String] = implicitly[FunctorL[F]].extension_map(fa)(_.toString()) - def toStringOnFunctor[F[_]: Functor, A](fa: F[A]): F[String] = implicitly[Functor[F]].extension_map(fa)(_.toString()) - def hashOnFunctorI[F[_]: FunctorI, A <: Int](fa: F[A]): F[Int] = implicitly[FunctorI[F]].extension_map(fa)(_.##) + def toStringOnFunctorL[F[X] <: List[X]: FunctorL, A](fa: F[A]): F[String] = implicitly[FunctorL[F]].map(fa)(_.toString()) + def toStringOnFunctor[F[_]: Functor, A](fa: F[A]): F[String] = implicitly[Functor[F]].map(fa)(_.toString()) + def hashOnFunctorI[F[_]: FunctorI, A <: Int](fa: F[A]): F[Int] = implicitly[FunctorI[F]].map(fa)(_.##) test(assert(toStringOnFunctor(List(true,false)) === List("true","false"))) test(assert(hashOnFunctorI(List(1,2)) === List(1,2))) diff --git a/test/tasty/run/src-2/tastytest/TestMonad.scala b/test/tasty/run/src-2/tastytest/TestMonad.scala index 1dbe9c4d3ecc..524a82581a17 100644 --- a/test/tasty/run/src-2/tastytest/TestMonad.scala +++ b/test/tasty/run/src-2/tastytest/TestMonad.scala @@ -4,12 +4,12 @@ object TestMonad extends Suite("TestMonad") { implicit object ListMonad extends Monad[List] { def pure[A](x: A): List[A] = x :: Nil - def extension_flatMap[A, B](fa: List[A])(f: A => List[B]): List[B] = fa.flatMap(f) - override def extension_map[A, B](fa: List[A])(f: A => B): List[B] = fa.map(f) + def flatMap[A, B](fa: List[A])(f: A => List[B]): List[B] = fa.flatMap(f) + override def map[A, B](fa: List[A])(f: A => B): List[B] = fa.map(f) } def pureToString[F[_], A](fa: F[A])(implicit F: Monad[F]): F[String] = - F.extension_flatMap(fa)(a => F.pure(a.toString)) + F.flatMap(fa)(a => F.pure(a.toString)) test(assert(pureToString(List(1,2,3)) === List("1","2","3"))) diff --git a/test/tasty/run/src-2/tastytest/TestReader.scala b/test/tasty/run/src-2/tastytest/TestReader.scala index 4c6c10410ae5..4a7019600953 100644 --- a/test/tasty/run/src-2/tastytest/TestReader.scala +++ b/test/tasty/run/src-2/tastytest/TestReader.scala @@ -5,7 +5,7 @@ object TestReader extends Suite("TestReader") { implicit def mkReaderMonad[Ctx]: Reader[Ctx] = new Reader[Ctx]() {} def pureToString[F[_], A](fa: F[A])(implicit F: Monad[F]): F[String] = - F.extension_flatMap(fa)(a => F.pure(a.toString)) + F.flatMap(fa)(a => F.pure(a.toString)) test { val f = pureToString((s: Unit) => 101) diff --git a/test/tasty/run/src-2/tastytest/TestRefinements.scala b/test/tasty/run/src-2/tastytest/TestRefinements.scala index b1191206faf0..897c0fe57192 100644 --- a/test/tasty/run/src-2/tastytest/TestRefinements.scala +++ b/test/tasty/run/src-2/tastytest/TestRefinements.scala @@ -129,7 +129,7 @@ object TestRefinements extends Suite("TestRefinements") { def create: EncoderIntSel = { new Refinements.MethodSelectable( - method("encode", ClassTag.Int) { xs => xs.head.toString } + method("encode", classOf[Int]) { xs => xs.head.toString } ).asInstanceOf[EncoderIntSel] } } diff --git a/test/tasty/run/src-2/tastytest/TestSymbollicEnums.scala b/test/tasty/run/src-2/tastytest/TestSymbollicEnums.scala index a246f5e78932..4b342cbd64ff 100644 --- a/test/tasty/run/src-2/tastytest/TestSymbollicEnums.scala +++ b/test/tasty/run/src-2/tastytest/TestSymbollicEnums.scala @@ -9,11 +9,11 @@ object TestSymbollicEnums extends Suite("TestSymbollicEnums") { val zero = 0L.lit val one = 1L.lit - def extension_interpret(e: Expr[Long]): Long = e match { + def interpret(e: Expr[Long]): Long = e match { case Expr.Literal(x) => x case Expr.Infix(op, l, r) => op match { - case Ops.+ => extension_interpret(l) + extension_interpret(r) - case Ops.* => extension_interpret(l) * extension_interpret(r) + case Ops.+ => interpret(l) + interpret(r) + case Ops.* => interpret(l) * interpret(r) } } } diff --git a/test/tasty/run/src-3/tastytest/MacroCompat.scala b/test/tasty/run/src-3/tastytest/MacroCompat.scala index e1faf813a2bf..71ba8c03f063 100644 --- a/test/tasty/run/src-3/tastytest/MacroCompat.scala +++ b/test/tasty/run/src-3/tastytest/MacroCompat.scala @@ -24,17 +24,18 @@ object MacroCompat { object Macros3 { import quoted._ - def monoImpl(using QuoteContext) = '{1} - def polyImpl[T: Type](using QuoteContext) = Expr(summon[Type[T]].show) - - def posImpl(using qctx: QuoteContext): Expr[Position] = { - import qctx.reflect.given - val name = qctx.reflect.rootPosition.sourceFile.jpath.getFileName.toString - val line = qctx.reflect.rootPosition.startLine + 1 + def monoImpl(using Quotes) = '{1} + def polyImpl[T: Type](using quotes: Quotes) = Expr(quotes.reflect.TypeRepr.of[T].show) + + def posImpl(using quotes: Quotes): Expr[Position] = { + import quotes.reflect.given + val pos = quotes.reflect.Position.ofMacroExpansion + val name = pos.sourceFile.jpath.getFileName.toString + val line = pos.startLine + 1 '{ Position(${Expr(name)}, ${Expr(line)}) } } - def constIntImpl[T: Type](x: Expr[T])(using QuoteContext): Expr[Int] = '{1} + def constIntImpl[T: Type](x: Expr[T])(using Quotes): Expr[Int] = '{1} } diff --git a/test/tasty/run/src-3/tastytest/Monad.scala b/test/tasty/run/src-3/tastytest/Monad.scala index b3d0eade02c1..5a1bf297eff4 100644 --- a/test/tasty/run/src-3/tastytest/Monad.scala +++ b/test/tasty/run/src-3/tastytest/Monad.scala @@ -4,6 +4,6 @@ trait Monad[F[_]] extends Functor[F] { def pure[A](x: A): F[A] extension [A, B](fa: F[A]) { def flatMap(f: A => F[B]): F[B] - def map (f: A => B) = extension_flatMap(fa)(f `andThen` pure) + def map (f: A => B) = flatMap(f `andThen` pure) } } diff --git a/test/tasty/run/src-3/tastytest/Refinements.scala b/test/tasty/run/src-3/tastytest/Refinements.scala index cb974ea191ad..5f4c6b91c3d0 100644 --- a/test/tasty/run/src-3/tastytest/Refinements.scala +++ b/test/tasty/run/src-3/tastytest/Refinements.scala @@ -178,15 +178,15 @@ object Refinements { extends scala.Selectable { private val map = methods.toMap - def applyDynamic(name: String, paramClasses: ClassTag[_]*)(args: Any*): Any = + def applyDynamic(name: String, paramClasses: Class[_]*)(args: Any*): Any = map.get(name, paramClasses) match case Some(f) => f(args) case None => throw NoSuchMethodException(s"$name(${paramClasses.mkString(",")})") } object MethodSelectable { - type Method = ((String, Seq[ClassTag[_]]), Seq[Any] => Any) - def method(name: String, paramClasses: ClassTag[_]*)(impl: Seq[Any] => Any): Method = + type Method = ((String, Seq[Class[_]]), Seq[Any] => Any) + def method(name: String, paramClasses: Class[_]*)(impl: Seq[Any] => Any): Method = ((name, paramClasses), impl) } diff --git a/test/tasty/run/src-3/tastytest/SuperOps.scala b/test/tasty/run/src-3/tastytest/SuperOps.scala index ee1f89f73d64..f94984c9c0d3 100644 --- a/test/tasty/run/src-3/tastytest/SuperOps.scala +++ b/test/tasty/run/src-3/tastytest/SuperOps.scala @@ -1,3 +1,3 @@ package tastytest -super trait SuperOps[Impl <: SuperOps[Impl]] +transparent trait SuperOps[Impl <: SuperOps[Impl]]