diff --git a/compiler/src/dotty/tools/backend/jvm/BTypesFromSymbols.scala b/compiler/src/dotty/tools/backend/jvm/BTypesFromSymbols.scala index 09120f742156..8044bb7496e8 100644 --- a/compiler/src/dotty/tools/backend/jvm/BTypesFromSymbols.scala +++ b/compiler/src/dotty/tools/backend/jvm/BTypesFromSymbols.scala @@ -61,7 +61,7 @@ class BTypesFromSymbols[I <: BackendInterface](val int: I) extends BTypes { } private def setClassInfo(classSym: Symbol, classBType: ClassBType): ClassBType = { - val superClassSym = if (classSym.isImplClass) ObjectClass else classSym.superClass + val superClassSym = classSym.superClass assert( if (classSym == ObjectClass) superClassSym == NoSymbol diff --git a/compiler/src/dotty/tools/backend/jvm/BackendInterface.scala b/compiler/src/dotty/tools/backend/jvm/BackendInterface.scala index 11f251ae0600..091e3eecd78b 100644 --- a/compiler/src/dotty/tools/backend/jvm/BackendInterface.scala +++ b/compiler/src/dotty/tools/backend/jvm/BackendInterface.scala @@ -484,7 +484,6 @@ abstract class BackendInterface extends BackendInterfaceDefinitions { def isStrictFP: Boolean def isLabel: Boolean def hasPackageFlag: Boolean - def isImplClass: Boolean def isInterface: Boolean def isGetter: Boolean def isSetter: Boolean diff --git a/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala b/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala index a5683b5afe02..e2fcb3c61e38 100644 --- a/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala +++ b/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala @@ -666,7 +666,6 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma def isStrictFP: Boolean = false // todo: implement def isLabel: Boolean = sym is Flags.Label def hasPackageFlag: Boolean = sym is Flags.Package - def isImplClass: Boolean = sym is Flags.ImplClass def isInterface: Boolean = (sym is Flags.PureInterface) || (sym is Flags.Trait) def isGetter: Boolean = toDenot(sym).isGetter def isSetter: Boolean = toDenot(sym).isSetter @@ -683,7 +682,7 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma def isFinal: Boolean = sym is Flags.Final def isStaticMember: Boolean = (sym ne NoSymbol) && - ((sym is Flags.JavaStatic) || (owner is Flags.ImplClass) || toDenot(sym).hasAnnotation(ctx.definitions.ScalaStaticAnnot)) + ((sym is Flags.JavaStatic) || toDenot(sym).hasAnnotation(ctx.definitions.ScalaStaticAnnot)) // guard against no sumbol cause this code is executed to select which call type(static\dynamic) to use to call array.clone def isBottomClass: Boolean = (sym ne defn.NullClass) && (sym ne defn.NothingClass) @@ -701,7 +700,7 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma def isNonBottomSubClass(other: Symbol): Boolean = sym.derivesFrom(other) def hasAnnotation(ann: Symbol): Boolean = toDenot(sym).hasAnnotation(ann) def shouldEmitForwarders: Boolean = - (sym is Flags.Module) && !(sym is Flags.ImplClass) && sym.isStatic + (sym is Flags.Module) && sym.isStatic def isJavaEntryPoint: Boolean = CollectEntryPoints.isJavaEntryPoint(sym) def isClassConstructor: Boolean = toDenot(sym).isClassConstructor diff --git a/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala b/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala index 90839465a6e1..9476d43cb380 100644 --- a/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala +++ b/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala @@ -1575,8 +1575,6 @@ class JSCodeGen()(implicit ctx: Context) { genApplyJSMethodGeneric(tree, sym, genExpr(receiver), genActualJSArgs(sym, args), isStat) /*else genApplyJSClassMethod(genExpr(receiver), sym, genActualArgs(sym, args))*/ - } else if (foreignIsImplClass(sym.owner)) { - genTraitImplApply(sym, args.map(genExpr)) } else if (sym.isClassConstructor) { // Calls to constructors are always statically linked genApplyMethodStatically(genExpr(receiver), sym, genActualArgs(sym, args)) @@ -2022,12 +2020,6 @@ class JSCodeGen()(implicit ctx: Context) { toIRType(patchedResultType(method))) } - /** Gen a call to a Scala2 impl class method. */ - private def genTraitImplApply(method: Symbol, arguments: List[js.Tree])( - implicit pos: Position): js.Tree = { - genApplyStatic(method, arguments) - } - /** Gen a call to a non-exposed method of a non-native JS class. */ private def genApplyJSClassMethod(receiver: js.Tree, method: Symbol, arguments: List[js.Tree])(implicit pos: Position): js.Tree = { diff --git a/compiler/src/dotty/tools/backend/sjs/JSEncoding.scala b/compiler/src/dotty/tools/backend/sjs/JSEncoding.scala index 95ee81515edf..a18bceb165b4 100644 --- a/compiler/src/dotty/tools/backend/sjs/JSEncoding.scala +++ b/compiler/src/dotty/tools/backend/sjs/JSEncoding.scala @@ -185,9 +185,6 @@ object JSEncoding { js.Ident(localNames.localSymbolName(sym), Some(sym.unexpandedName.decoded)) } - def foreignIsImplClass(sym: Symbol)(implicit ctx: Context): Boolean = - sym.name.endsWith(nme.IMPL_CLASS_SUFFIX.toString) - def encodeClassType(sym: Symbol)(implicit ctx: Context): jstpe.Type = { if (sym == defn.ObjectClass) jstpe.AnyType else if (isJSType(sym)) jstpe.AnyType diff --git a/compiler/src/dotty/tools/dotc/Compiler.scala b/compiler/src/dotty/tools/dotc/Compiler.scala index 0157a095cd0b..96404798a651 100644 --- a/compiler/src/dotty/tools/dotc/Compiler.scala +++ b/compiler/src/dotty/tools/dotc/Compiler.scala @@ -81,7 +81,7 @@ class Compiler { new ElimByName, // Expand by-name parameter references new CollectNullableFields, // Collect fields that can be nulled out after use in lazy initialization new ElimOuterSelect, // Expand outer selections - new AugmentScala2Traits, // Expand traits defined in Scala 2.x to simulate old-style rewritings + new AugmentScala2Traits, // Augments Scala2 traits with additional members needed for mixin composition. new ResolveSuper, // Implement super accessors and add forwarders to trait methods new FunctionXXLForwarders, // Add forwarders for FunctionXXL apply method new ArrayConstructors) :: // Intercept creation of (non-generic) arrays and intrinsify. diff --git a/compiler/src/dotty/tools/dotc/core/Flags.scala b/compiler/src/dotty/tools/dotc/core/Flags.scala index dca30ce1f82c..479b6753a09e 100644 --- a/compiler/src/dotty/tools/dotc/core/Flags.scala +++ b/compiler/src/dotty/tools/dotc/core/Flags.scala @@ -340,6 +340,8 @@ object Flags { /** An unpickled Scala 2.x class */ final val Scala2x: FlagSet = typeFlag(26, "") + final val Scala2xTrait: FlagSet = Scala2x | Trait + final val SuperAccessorOrScala2x: FlagSet = Scala2x.toCommonFlags /** A method that has default params */ @@ -413,11 +415,6 @@ object Flags { /** Symbol is a self name */ final val SelfName: FlagSet = termFlag(54, "") - /** Symbol is an implementation class of a Scala2 trait */ - final val ImplClass: FlagSet = typeFlag(54, "") - - final val SelfNameOrImplClass: FlagSet = SelfName.toCommonFlags - /** An existentially bound symbol (Scala 2.x only) */ final val Scala2ExistentialCommon: FlagSet = commonFlag(55, "") final val Scala2Existential: FlagSet = Scala2ExistentialCommon.toTypeFlags @@ -428,14 +425,11 @@ object Flags { /** A module variable (Scala 2.x only) */ final val Scala2ModuleVar: FlagSet = termFlag(57, "") - /** A Scala 2.12 trait that has been augmented with static members */ - final val Scala_2_12_Augmented: FlagSet = typeFlag(57, "") - - /** A definition that's initialized before the super call (Scala 2.x only) */ - final val Scala2PreSuper: FlagSet = termFlag(58, "") - - /** A Scala 2.12 or higher trait */ - final val Scala_2_12_Trait: FlagSet = typeFlag(58, "") + /** A Scala 2.x trait that has been partially augmented. + * This is set in `AugmentScala2Trait` and reset in `LinkScala2Impls` + * when the trait is fully augmented. + */ + final val Scala2xPartiallyAugmented: FlagSet = typeFlag(57, "") /** A macro */ final val Macro: FlagSet = commonFlag(59, "") @@ -497,7 +491,7 @@ object Flags { * is completed) */ final val AfterLoadFlags: FlagSet = - FromStartFlags | AccessFlags | Final | AccessorOrSealed | LazyOrTrait | SelfNameOrImplClass + FromStartFlags | AccessFlags | Final | AccessorOrSealed | LazyOrTrait | SelfName.toCommonFlags assert(FromStartFlags.isTermFlags && FromStartFlags.isTypeFlags) // TODO: Should check that FromStartFlags do not change in completion @@ -549,7 +543,7 @@ object Flags { /** Flags that can apply to a module class */ final val RetainedModuleClassFlags: FlagSet = RetainedModuleValAndClassFlags | - ImplClass | Enum | Opaque + Enum | Opaque /** Flags that are copied from a synthetic companion to a user-defined one * when the two are merged. See: Namer.mergeCompanionDefs diff --git a/compiler/src/dotty/tools/dotc/core/Mode.scala b/compiler/src/dotty/tools/dotc/core/Mode.scala index 1d794486aea1..57fd67956205 100644 --- a/compiler/src/dotty/tools/dotc/core/Mode.scala +++ b/compiler/src/dotty/tools/dotc/core/Mode.scala @@ -69,9 +69,6 @@ object Mode { /** We are currently unpickling Scala2 info */ val Scala2Unpickling: Mode = newMode(13, "Scala2Unpickling") - /** We are currently unpickling from Java 8 or higher */ - val Java8Unpickling: Mode = newMode(14, "Java8Unpickling") - /** Use Scala2 scheme for overloading and implicit resolution */ val OldOverloadingResolution: Mode = newMode(15, "OldOverloadingResolution") diff --git a/compiler/src/dotty/tools/dotc/core/NameOps.scala b/compiler/src/dotty/tools/dotc/core/NameOps.scala index 7f26a68687fe..91b1d611bee2 100644 --- a/compiler/src/dotty/tools/dotc/core/NameOps.scala +++ b/compiler/src/dotty/tools/dotc/core/NameOps.scala @@ -141,14 +141,6 @@ object NameOps { name.replace { case VariantName(invariant, _) => invariant } } - def implClassName: N = likeSpacedN(name ++ tpnme.IMPL_CLASS_SUFFIX) - - def traitOfImplClassName: N = { - val suffix = tpnme.IMPL_CLASS_SUFFIX.toString - assert(name.endsWith(suffix), name) - likeSpacedN(name.mapLast(_.dropRight(suffix.length))) - } - def errorName: N = likeSpacedN(name ++ nme.ERROR) /** Map variance value -1, +1 to 0, 1 */ diff --git a/compiler/src/dotty/tools/dotc/core/StdNames.scala b/compiler/src/dotty/tools/dotc/core/StdNames.scala index 85d4d4832f1b..2f89a4eb18f6 100644 --- a/compiler/src/dotty/tools/dotc/core/StdNames.scala +++ b/compiler/src/dotty/tools/dotc/core/StdNames.scala @@ -128,7 +128,6 @@ object StdNames { val EMPTY_PACKAGE: N = "" val EXCEPTION_RESULT_PREFIX: N = "exceptionResult" val EXPAND_SEPARATOR: N = str.EXPAND_SEPARATOR - val IMPL_CLASS_SUFFIX: N = "$class" val IMPORT: N = "" val MODULE_SUFFIX: N = str.MODULE_SUFFIX val OPS_PACKAGE: N = "" diff --git a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala index ab0e9b3ed9d4..84e8384d3459 100644 --- a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala @@ -650,9 +650,6 @@ object SymDenotations { /** is this the constructor of a class? */ final def isClassConstructor: Boolean = name == nme.CONSTRUCTOR - /** Is this the constructor of a trait? */ - final def isImplClassConstructor: Boolean = name == nme.TRAIT_CONSTRUCTOR - /** Is this the constructor of a trait or a class */ final def isConstructor: Boolean = name.isConstructorName @@ -757,7 +754,6 @@ object SymDenotations { || boundary.isRoot || (accessWithin(boundary) || accessWithinLinked(boundary)) && ( !(this is Local) - || (owner is ImplClass) // allow private local accesses to impl class members || isCorrectThisType(pre) ) || (this is Protected) && @@ -1901,8 +1897,7 @@ object SymDenotations { override def primaryConstructor(implicit ctx: Context): Symbol = { def constrNamed(cname: TermName) = info.decls.denotsNamed(cname).last.symbol // denotsNamed returns Symbols in reverse order of occurrence - if (this.is(ImplClass)) constrNamed(nme.TRAIT_CONSTRUCTOR) // ignore normal constructor - else if (this.is(Package)) NoSymbol + if (this.is(Package)) NoSymbol else constrNamed(nme.CONSTRUCTOR).orElse(constrNamed(nme.TRAIT_CONSTRUCTOR)) } diff --git a/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala index 66b9079b299e..790b6cc403e8 100644 --- a/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala +++ b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala @@ -99,8 +99,6 @@ class ClassfileParser( throw new IOException(s"class file '${in.file}' has wrong magic number 0x${toHexString(magic)}, should be 0x${toHexString(JAVA_MAGIC)}") val minorVersion = in.nextChar.toInt val majorVersion = in.nextChar.toInt - if (majorVersion >= JAVA8_MAJOR_VERSION) - Scala2UnpicklingMode |= Mode.Java8Unpickling if ((majorVersion < JAVA_MAJOR_VERSION) || ((majorVersion == JAVA_MAJOR_VERSION) && (minorVersion < JAVA_MINOR_VERSION))) diff --git a/compiler/src/dotty/tools/dotc/core/unpickleScala2/PickleBuffer.scala b/compiler/src/dotty/tools/dotc/core/unpickleScala2/PickleBuffer.scala index 0c97afb20d15..78014fba2ce6 100644 --- a/compiler/src/dotty/tools/dotc/core/unpickleScala2/PickleBuffer.scala +++ b/compiler/src/dotty/tools/dotc/core/unpickleScala2/PickleBuffer.scala @@ -230,7 +230,6 @@ object PickleBuffer { LAZY -> Lazy, MIXEDIN -> (MixedIn, Scala2Existential), EXPANDEDNAME -> Scala2ExpandedName, - IMPLCLASS -> (Scala2PreSuper, ImplClass), SPECIALIZED -> Specialized, VBRIDGE -> EmptyFlags, VARARGS -> JavaVarargs, diff --git a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Flags.scala b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Flags.scala index 5025a7a54997..1624f90e80fc 100644 --- a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Flags.scala +++ b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Flags.scala @@ -80,7 +80,6 @@ object Scala2Flags { final val MIXEDIN = 1L << 35 // term member has been mixed in final val EXISTENTIAL = 1L << 35 // type is an existential parameter or skolem final val EXPANDEDNAME = 1L << 36 // name has been expanded with class suffix - final val IMPLCLASS = 1L << 37 // symbol is an implementation class final val TRANS_FLAG = 1L << 38 // transient flag guaranteed to be reset after each phase. final val LOCKED = 1L << 39 // temporary flag to catch cyclic dependencies diff --git a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala index 62fc814003df..d7d934d2805d 100644 --- a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala @@ -474,8 +474,6 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas def finishSym(sym: Symbol): Symbol = { if (sym.isClass) { sym.setFlag(Scala2x) - if (flags.is(Trait) && ctx.mode.is(Mode.Java8Unpickling)) - sym.setFlag(Scala_2_12_Trait) } if (!(isRefinementClass(sym) || isUnpickleRoot(sym) || (sym is Scala2Existential))) { val owner = sym.owner diff --git a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala index a30ddea7af1c..34e26a4b8ceb 100644 --- a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala @@ -368,7 +368,6 @@ class PlainPrinter(_ctx: Context) extends Printer { else if (sym.isAnonymousClass) "anonymous class" else if (flags is ModuleClass) "module class" else if (flags is ModuleVal) "module" - else if (flags is ImplClass) "implementation class" else if (flags is Trait) "trait" else if (sym.isClass) "class" else if (sym.isType) "type" diff --git a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala index 8a03f518e634..b5cc53874251 100644 --- a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala @@ -833,7 +833,6 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { if (flags is Package) "package" else if (sym.isPackageObject) "package object" else if (flags is Module) "object" - else if (flags is ImplClass) "class" else if (sym.isClassConstructor) "constructor" else super.kindString(sym) } diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/KernelImpl.scala b/compiler/src/dotty/tools/dotc/tastyreflect/KernelImpl.scala index 87d9791322fb..2dfa27bde725 100644 --- a/compiler/src/dotty/tools/dotc/tastyreflect/KernelImpl.scala +++ b/compiler/src/dotty/tools/dotc/tastyreflect/KernelImpl.scala @@ -1611,7 +1611,6 @@ class KernelImpl(val rootContext: core.Contexts.Context, val rootPosition: util. def Flags_ModuleClass: Flags = core.Flags.ModuleClass def Flags_PrivateLocal: Flags = core.Flags.PrivateLocal def Flags_Package: Flags = core.Flags.Package - def Flags_ImplClass: Flags = core.Flags.ImplClass // // QUOTED SEAL/UNSEAL diff --git a/compiler/src/dotty/tools/dotc/transform/AugmentScala2Traits.scala b/compiler/src/dotty/tools/dotc/transform/AugmentScala2Traits.scala index b1ba4d987131..d63d7303a1f4 100644 --- a/compiler/src/dotty/tools/dotc/transform/AugmentScala2Traits.scala +++ b/compiler/src/dotty/tools/dotc/transform/AugmentScala2Traits.scala @@ -14,93 +14,59 @@ import Annotations._ import StdNames._ import NameOps._ import NameKinds.{ExpandedName, TraitSetterName} +import ast.Trees._ object AugmentScala2Traits { val name: String = "augmentScala2Traits" } -/** This phase augments Scala2 traits with implementation classes and with additional members - * needed for mixin composition. - * These symbols would have been added between Unpickling and Mixin in the Scala2 pipeline. - * Specifically, it adds +/** This phase augments Scala2 traits with additional members needed for mixin composition. * - * - an implementation class which defines a trait constructor and trait method implementations - * - trait setters for vals defined in traits + * These symbols would have been added between Unpickling and Mixin in the Scala2 pipeline. * - * Furthermore, it expands the names of all private getters and setters as well as super accessors in the trait and makes - * them not-private. + * Specifically, we: + * - Mark all lazy val fields as @volatile to get the proper Scala 2 semantics. + * - Add trait setters for vals defined in traits. + * - Expand the names of all private getters and setters as well as super accessors in the trait and make + * not-private. */ -class AugmentScala2Traits extends MiniPhase with IdentityDenotTransformer with FullParameterization { thisPhase => +class AugmentScala2Traits extends MiniPhase with IdentityDenotTransformer { thisPhase => import ast.tpd._ override def changesMembers: Boolean = true override def phaseName: String = AugmentScala2Traits.name - override def rewiredTarget(referenced: Symbol, derived: Symbol)(implicit ctx: Context): Symbol = NoSymbol - override def transformTemplate(impl: Template)(implicit ctx: Context): Template = { val cls = impl.symbol.owner.asClass - for (mixin <- cls.mixins) - if (mixin.is(Scala2x)) - augmentScala2Trait(mixin, cls) + for (mixin <- cls.mixins if mixin.is(Scala2x) && !mixin.is(Scala2xPartiallyAugmented)) + augmentScala2Trait(mixin) impl } - private def augmentScala2Trait(mixin: ClassSymbol, cls: ClassSymbol)(implicit ctx: Context): Unit = { - if (mixin.implClass.is(Scala2x)) () // nothing to do, mixin was already augmented - else { - //println(i"creating new implclass for $mixin ${mixin.implClass}") - val ops = new MixinOps(cls, thisPhase) - import ops._ - - val implClass = ctx.newCompleteClassSymbol( - owner = mixin.owner, - name = mixin.name.implClassName, - flags = Abstract | Scala2x | ImplClass, - parents = defn.ObjectType :: Nil, - assocFile = mixin.assocFile).enteredAfter(thisPhase) - - def implMethod(meth: TermSymbol): Symbol = { - val mold = - if (meth.isConstructor) - meth.copySymDenotation( - name = nme.TRAIT_CONSTRUCTOR, - info = MethodType(Nil, defn.UnitType)) - else meth.ensureNotPrivate - meth.copy( - owner = implClass, - name = mold.name.asTermName, - flags = Method | JavaStatic, - info = fullyParameterizedType(mold.info, mixin)) - } - - def traitSetter(getter: TermSymbol) = - getter.copy( - name = getter.ensureNotPrivate.name - .expandedName(getter.owner, TraitSetterName) - .asTermName.setterName, - flags = Method | Accessor, - info = MethodType(getter.info.resultType :: Nil, defn.UnitType)) + private def augmentScala2Trait(mixin: ClassSymbol)(implicit ctx: Context): Unit = { + def traitSetter(getter: TermSymbol) = + getter.copy( + name = getter.ensureNotPrivate.name + .expandedName(getter.owner, TraitSetterName) + .asTermName.setterName, + flags = Method | Accessor, + info = MethodType(getter.info.resultType :: Nil, defn.UnitType)) - for (sym <- mixin.info.decls) { - if (needsForwarder(sym) || sym.isConstructor || sym.isGetter && sym.is(Lazy) || sym.is(Method, butNot = Deferred)) - implClass.enter(implMethod(sym.asTerm)) - if (sym.isGetter) - if (sym.is(Lazy)) { - if (!sym.hasAnnotation(defn.VolatileAnnot)) - sym.addAnnotation(Annotation(defn.VolatileAnnot, Nil)) - } - else if (!sym.is(Deferred) && !sym.setter.exists && - !sym.info.resultType.isInstanceOf[ConstantType]) - traitSetter(sym.asTerm).enteredAfter(thisPhase) - if ((sym.is(PrivateAccessor) && !sym.name.is(ExpandedName) && - (sym.isGetter || sym.isSetter)) // strangely, Scala 2 fields are also methods that have Accessor set. - || sym.isSuperAccessor) // scala2 superaccessors are pickled as private, but are compiled as public expanded - sym.ensureNotPrivate.installAfter(thisPhase) - } - ctx.log(i"Scala2x trait decls of $mixin = ${mixin.info.decls.toList.map(_.showDcl)}%\n %") - ctx.log(i"Scala2x impl decls of $mixin = ${implClass.info.decls.toList.map(_.showDcl)}%\n %") + for (sym <- mixin.info.decls) { + if (sym.isGetter) + if (sym.is(Lazy)) { + if (!sym.hasAnnotation(defn.VolatileAnnot)) + sym.addAnnotation(Annotation(defn.VolatileAnnot, Nil)) + } + else if (!sym.is(Deferred) && !sym.setter.exists && + !sym.info.resultType.isInstanceOf[ConstantType]) + traitSetter(sym.asTerm).enteredAfter(thisPhase) + if ((sym.is(PrivateAccessor) && !sym.name.is(ExpandedName) && + (sym.isGetter || sym.isSetter)) // strangely, Scala 2 fields are also methods that have Accessor set. + || sym.isSuperAccessor) // scala2 superaccessors are pickled as private, but are compiled as public expanded + sym.ensureNotPrivate.installAfter(thisPhase) } + mixin.setFlag(Scala2xPartiallyAugmented) } } diff --git a/compiler/src/dotty/tools/dotc/transform/LinkScala2Impls.scala b/compiler/src/dotty/tools/dotc/transform/LinkScala2Impls.scala index a6768fced4ec..f84eb86f2a42 100644 --- a/compiler/src/dotty/tools/dotc/transform/LinkScala2Impls.scala +++ b/compiler/src/dotty/tools/dotc/transform/LinkScala2Impls.scala @@ -18,16 +18,11 @@ import NameKinds.ImplMethName * * super[M].f(args) * - * where M is a Scala 2.11 trait implemented by the current class to + * where M is a Scala 2.x trait implemented by the current class to * - * M$class.f(this, args) + * M.f$(this, args) * - * provided the implementation class M$class defines a corresponding function `f`. - * If M is a Scala 2.12 or newer trait, rewrite to - * - * M.f(this, args) - * - * where f is a static member of M. + * where f$ is a static member of M. */ class LinkScala2Impls extends MiniPhase with IdentityDenotTransformer { thisPhase => import ast.tpd._ @@ -39,32 +34,40 @@ class LinkScala2Impls extends MiniPhase with IdentityDenotTransformer { thisPhas // Adds as a side effect static members to traits which can confuse Mixin, // that's why it is runsAfterGroupOf - /** Copy definitions from implementation class to trait itself */ - private def augmentScala_2_12_Trait(mixin: ClassSymbol)(implicit ctx: Context): Unit = { - def info_2_12(sym: Symbol) = sym.info match { - case mt @ MethodType(paramNames @ nme.SELF :: _) => - // 2.12 seems to always assume the enclsing mixin class as self type parameter, - // whereas 2.11 used the self type of this class instead. - val selfType :: otherParamTypes = mt.paramInfos - MethodType(paramNames, mixin.typeRef :: otherParamTypes, mt.resType) - case info => info + private def addStaticForwarders(mixin: ClassSymbol)(implicit ctx: Context): Unit = { + val ops = new MixinOps(mixin, thisPhase) + import ops._ + + def newImpl(meth: TermSymbol): Symbol = { + def staticInfo(tp: Type) = tp match { + case mt: MethodType => + MethodType(nme.SELF :: mt.paramNames, mixin.typeRef :: mt.paramInfos, mt.resType) + } + val mold = + if (meth.isConstructor) + meth.copySymDenotation( + name = nme.TRAIT_CONSTRUCTOR, + info = MethodType(Nil, defn.UnitType)) + else meth.ensureNotPrivate + meth.copy( + owner = mixin, + name = if (meth.isConstructor) mold.name.asTermName else ImplMethName(mold.name.asTermName), + flags = Method | JavaStatic, + info = staticInfo(mold.info) + ) } - def newImpl(sym: TermSymbol): Symbol = sym.copy( - owner = mixin, - name = if (sym.isConstructor) sym.name else ImplMethName(sym.name), - info = info_2_12(sym) - ) - for (sym <- mixin.implClass.info.decls) - newImpl(sym.asTerm).enteredAfter(thisPhase) + for (sym <- mixin.info.decls) { + if (needsForwarder(sym) || sym.isConstructor || sym.isGetter && sym.is(Lazy) || sym.is(Method, butNot = Deferred)) + newImpl(sym.asTerm).enteredAfter(thisPhase) + } + // The trait is now fully augmented so the flag isn't needed anymore. + mixin.resetFlag(Scala2xPartiallyAugmented) } override def prepareForTemplate(impl: Template)(implicit ctx: Context): Context = { val cls = impl.symbol.owner.asClass - for (mixin <- cls.mixins) - if (mixin.is(Scala_2_12_Trait, butNot = Scala_2_12_Augmented)) { - augmentScala_2_12_Trait(mixin) - mixin.setFlag(Scala_2_12_Augmented) - } + for (mixin <- cls.mixins if (mixin.is(Scala2xPartiallyAugmented))) + addStaticForwarders(mixin) ctx } @@ -72,14 +75,10 @@ class LinkScala2Impls extends MiniPhase with IdentityDenotTransformer { thisPhas def currentClass = ctx.owner.enclosingClass.asClass app match { case Apply(sel @ Select(Super(_, _), _), args) - if sel.symbol.owner.is(Scala2xTrait) && currentClass.mixins.contains(sel.symbol.owner) => + if sel.symbol.owner.is(Scala2x) && currentClass.mixins.contains(sel.symbol.owner) => val impl = implMethod(sel.symbol) if (impl.exists) Apply(ref(impl), This(currentClass) :: args).withSpan(app.span) else app // could have been an abstract method in a trait linked to from a super constructor - case Apply(sel, args) - if sel.symbol.maybeOwner.is(ImplClass) && sel.symbol.owner.traitOfImplClass.is(Scala_2_12_Trait) => - val impl = implMethod(sel.symbol) - cpy.Apply(app)(ref(impl), args) case _ => app } @@ -89,9 +88,7 @@ class LinkScala2Impls extends MiniPhase with IdentityDenotTransformer { thisPhas private def implMethod(meth: Symbol)(implicit ctx: Context): Symbol = { val implName = ImplMethName(meth.name.asTermName) val cls = meth.owner - if (cls.is(ImplClass)) - cls.traitOfImplClass.info.decl(implName).atSignature(meth.signature).symbol - else if (cls.is(Scala_2_12_Trait)) + if (cls.is(Scala2xTrait)) if (meth.isConstructor) cls.info.decl(nme.TRAIT_CONSTRUCTOR).symbol else diff --git a/compiler/src/dotty/tools/dotc/transform/Mixin.scala b/compiler/src/dotty/tools/dotc/transform/Mixin.scala index bc925f6a9aad..1d7029c8433b 100644 --- a/compiler/src/dotty/tools/dotc/transform/Mixin.scala +++ b/compiler/src/dotty/tools/dotc/transform/Mixin.scala @@ -59,19 +59,23 @@ object Mixin { * 3.2 (done in `traitInits`) For every concrete trait getter ` def x(): T` in M * which is not a parameter accessor, in order of textual occurrence, produce the following: * - * 3.2.1 If `x` is also a member of `C`, and M is a Dotty trait: + * 3.2.1 If `x` is also a member of `C`, and is a lazy val, + * + * lazy val x: T = super[M].x + * + * 3.2.2 If `x` is also a member of `C`, and M is a Dotty trait, * * def x(): T = super[M].initial$x() * - * 3.2.2 If `x` is also a member of `C`, and M is a Scala 2.x trait: + * 3.2.3 If `x` is also a member of `C`, and M is a Scala 2.x trait: * * def x(): T = _ * - * 3.2.3 If `x` is not a member of `C`, and M is a Dotty trait: + * 3.2.4 If `x` is not a member of `C`, and M is a Dotty trait: * * super[M].initial$x() * - * 3.2.4 If `x` is not a member of `C`, and M is a Scala2.x trait, nothing gets added. + * 3.2.5 If `x` is not a member of `C`, and M is a Scala2.x trait, nothing gets added. * * * 3.3 (done in `superCallOpt`) The call: @@ -111,7 +115,7 @@ class Mixin extends MiniPhase with SymTransformer { thisPhase => else sym.copySymDenotation(initFlags = sym.flags &~ ParamAccessor | Deferred) sym1.ensureNotPrivate } - else if (sym.isConstructor && sym.owner.is(Trait)) + else if (sym.isConstructor && sym.owner.is(Trait, butNot = Scala2x)) sym.copySymDenotation( name = nme.TRAIT_CONSTRUCTOR, info = MethodType(Nil, sym.info.resultType)) @@ -220,26 +224,20 @@ class Mixin extends MiniPhase with SymTransformer { thisPhase => def default = Underscore(getter.info.resultType) def initial = transformFollowing(superRef(initializer(getter)).appliedToNone) - /** A call to the implementation of `getter` in `mixin`'s implementation class */ - def lazyGetterCall = { - def canbeImplClassGetter(sym: Symbol) = sym.info.firstParamTypes match { - case t :: Nil => t.isDirectRef(mixin) - case _ => false - } - val implClassGetter = mixin.implClass.info.nonPrivateDecl(getter.name) - .suchThat(canbeImplClassGetter).symbol - ref(mixin.implClass).select(implClassGetter).appliedTo(This(cls)) - } - if (isCurrent(getter) || getter.name.is(ExpandedName)) { val rhs = - if (was(getter, ParamAccessor)) nextArgument() - else if (isScala2x) - if (getter.is(Lazy, butNot = Module)) lazyGetterCall + if (was(getter, ParamAccessor)) + nextArgument() + else if (isScala2x) { + if (getter.is(Lazy, butNot = Module)) + initial else if (getter.is(Module)) New(getter.info.resultType, List(This(cls))) - else Underscore(getter.info.resultType) - else initial + else + Underscore(getter.info.resultType) + } + else + initial // transformFollowing call is needed to make memoize & lazy vals run transformFollowing(DefDef(implementation(getter.asTerm), rhs)) } diff --git a/compiler/src/dotty/tools/dotc/transform/MixinOps.scala b/compiler/src/dotty/tools/dotc/transform/MixinOps.scala index a78ee88886da..611c621f8750 100644 --- a/compiler/src/dotty/tools/dotc/transform/MixinOps.scala +++ b/compiler/src/dotty/tools/dotc/transform/MixinOps.scala @@ -63,6 +63,7 @@ class MixinOps(cls: ClassSymbol, thisPhase: DenotTransformer)(implicit ctx: Cont def needsDisambiguation = competingMethods.exists(x=> !(x is Deferred)) // multiple implementations are available def hasNonInterfaceDefinition = competingMethods.exists(!_.owner.is(Trait)) // there is a definition originating from class + !meth.isConstructor && meth.is(Method, butNot = PrivateOrAccessorOrDeferred) && (meth.owner.is(Scala2x) || needsDisambiguation || hasNonInterfaceDefinition || needsJUnit4Fix(meth) ) && isCurrent(meth) diff --git a/compiler/src/dotty/tools/dotc/transform/SelectStatic.scala b/compiler/src/dotty/tools/dotc/transform/SelectStatic.scala index 761d092da972..0203d456b68b 100644 --- a/compiler/src/dotty/tools/dotc/transform/SelectStatic.scala +++ b/compiler/src/dotty/tools/dotc/transform/SelectStatic.scala @@ -25,7 +25,6 @@ class SelectStatic extends MiniPhase with IdentityDenotTransformer { def isStaticMember = (sym is Flags.Module) && sym.initial.maybeOwner.initial.isStaticOwner || (sym is Flags.JavaStatic) || - (sym.maybeOwner is Flags.ImplClass) || sym.hasAnnotation(ctx.definitions.ScalaStaticAnnot) val isStaticRef = !sym.is(Package) && !sym.maybeOwner.is(Package) && isStaticMember val tree1 = diff --git a/compiler/src/dotty/tools/dotc/transform/SymUtils.scala b/compiler/src/dotty/tools/dotc/transform/SymUtils.scala index 355bef8f1268..af4c991b37be 100644 --- a/compiler/src/dotty/tools/dotc/transform/SymUtils.scala +++ b/compiler/src/dotty/tools/dotc/transform/SymUtils.scala @@ -111,12 +111,6 @@ class SymUtils(val self: Symbol) extends AnyVal { def isField(implicit ctx: Context): Boolean = self.isTerm && !self.is(Method) - def implClass(implicit ctx: Context): Symbol = - self.owner.info.decl(self.name.implClassName).symbol - - def traitOfImplClass(implicit ctx: Context): Symbol = - self.owner.info.decl(self.name.traitOfImplClassName).symbol - def annotationsCarrying(meta: ClassSymbol)(implicit ctx: Context): List[Annotation] = self.annotations.filter(_.symbol.hasAnnotation(meta)) diff --git a/library/src/scala/tasty/reflect/FlagsOps.scala b/library/src/scala/tasty/reflect/FlagsOps.scala index 4b5422fbc4af..0b52f1a3a416 100644 --- a/library/src/scala/tasty/reflect/FlagsOps.scala +++ b/library/src/scala/tasty/reflect/FlagsOps.scala @@ -115,9 +115,6 @@ trait FlagsOps extends Core { /** Is this symbol a package */ def Package: Flags = kernel.Flags_Package - - /** Is this symbol an implementation class of a Scala2 trait */ - def ImplClass: Flags = kernel.Flags_ImplClass } } diff --git a/library/src/scala/tasty/reflect/Kernel.scala b/library/src/scala/tasty/reflect/Kernel.scala index 00a1b5c4f94e..237b507bdc47 100644 --- a/library/src/scala/tasty/reflect/Kernel.scala +++ b/library/src/scala/tasty/reflect/Kernel.scala @@ -1321,7 +1321,6 @@ trait Kernel { def Flags_ModuleClass: Flags def Flags_PrivateLocal: Flags def Flags_Package: Flags - def Flags_ImplClass: Flags // // QUOTED SEAL/UNSEAL diff --git a/library/src/scala/tasty/reflect/Printers.scala b/library/src/scala/tasty/reflect/Printers.scala index 7bdc718789c5..1049dfc2a247 100644 --- a/library/src/scala/tasty/reflect/Printers.scala +++ b/library/src/scala/tasty/reflect/Printers.scala @@ -164,7 +164,6 @@ trait Printers if (flags.is(Flags.ModuleClass)) flagList += "Flags.ModuleClass" if (flags.is(Flags.PrivateLocal)) flagList += "Flags.PrivateLocal" if (flags.is(Flags.Package)) flagList += "Flags.Package" - if (flags.is(Flags.ImplClass)) flagList += "Flags.ImplClass" flagList.result().mkString(" | ") } @@ -540,7 +539,6 @@ trait Printers if (flags.is(Flags.ModuleClass)) flagList += "moduleClass" if (flags.is(Flags.PrivateLocal)) flagList += "private[this]" if (flags.is(Flags.Package)) flagList += "package" - if (flags.is(Flags.ImplClass)) flagList += "implClass" flagList.result().mkString("/*", " ", "*/") } diff --git a/semanticdb/src/dotty/semanticdb/SemanticdbConsumer.scala b/semanticdb/src/dotty/semanticdb/SemanticdbConsumer.scala index 91981fb6ed4c..63de499a730d 100644 --- a/semanticdb/src/dotty/semanticdb/SemanticdbConsumer.scala +++ b/semanticdb/src/dotty/semanticdb/SemanticdbConsumer.scala @@ -321,7 +321,7 @@ class SemanticdbConsumer(sourceFilePath: java.nio.file.Path) extends TastyConsum } def isStaticMember(implicit ctx: Context): Boolean = symbol.exists && - (symbol.flags.is(Flags.Static) || symbol.owner.flags.is(Flags.ImplClass) || + (symbol.flags.is(Flags.Static) || /*symbol.annots.find(_ == ctx.definitions.ScalaStaticAnnot)*/ false) def isStaticConstructor(implicit ctx: Context): Boolean = {