diff options
Diffstat (limited to 'compiler/src/dotty')
48 files changed, 675 insertions, 187 deletions
diff --git a/compiler/src/dotty/tools/FatalError.scala b/compiler/src/dotty/tools/FatalError.scala new file mode 100644 index 000000000..f75d5cf12 --- /dev/null +++ b/compiler/src/dotty/tools/FatalError.scala @@ -0,0 +1,3 @@ +package dotty.tools + +case class FatalError(msg: String) extends Exception(msg) diff --git a/compiler/src/dotty/tools/backend/jvm/CollectEntryPoints.scala b/compiler/src/dotty/tools/backend/jvm/CollectEntryPoints.scala index 2ee1b6011..0add25f3b 100644 --- a/compiler/src/dotty/tools/backend/jvm/CollectEntryPoints.scala +++ b/compiler/src/dotty/tools/backend/jvm/CollectEntryPoints.scala @@ -15,7 +15,6 @@ import java.io.{File => JFile} import scala.collection.generic.Clearable import scala.collection.mutable import scala.reflect.ClassTag -import scala.reflect.internal.util.WeakHashSet import scala.reflect.io.{Directory, PlainDirectory, AbstractFile} import scala.tools.asm.{ClassVisitor, FieldVisitor, MethodVisitor} import scala.tools.nsc.backend.jvm.{BCodeHelpers, BackendInterface} diff --git a/compiler/src/dotty/tools/backend/jvm/LabelDefs.scala b/compiler/src/dotty/tools/backend/jvm/LabelDefs.scala index 654507991..1950d300d 100644 --- a/compiler/src/dotty/tools/backend/jvm/LabelDefs.scala +++ b/compiler/src/dotty/tools/backend/jvm/LabelDefs.scala @@ -16,7 +16,6 @@ import scala.collection.generic.Clearable import scala.collection.mutable import scala.collection.mutable.{ListBuffer, ArrayBuffer} import scala.reflect.ClassTag -import scala.reflect.internal.util.WeakHashSet import scala.reflect.io.{Directory, PlainDirectory, AbstractFile} import scala.tools.asm.{ClassVisitor, FieldVisitor, MethodVisitor} import scala.tools.nsc.backend.jvm.{BCodeHelpers, BackendInterface} diff --git a/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala b/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala index e48b1039b..b00d7df71 100644 --- a/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala +++ b/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala @@ -26,18 +26,6 @@ trait TreeInfo[T >: Untyped <: Type] { self: Trees.Instance[T] => case _ => false } - /** The largest subset of {NoInits, PureInterface} that a - * trait enclosing this statement can have as flags. - * Does tree contain an initialization part when seen as a member of a class or trait? - */ - def defKind(tree: Tree): FlagSet = unsplice(tree) match { - case EmptyTree | _: Import => NoInitsInterface - case tree: TypeDef => if (tree.isClassDef) NoInits else NoInitsInterface - case tree: DefDef => if (tree.unforcedRhs == EmptyTree) NoInitsInterface else NoInits - case tree: ValDef => if (tree.unforcedRhs == EmptyTree) NoInitsInterface else EmptyFlags - case _ => EmptyFlags - } - def isOpAssign(tree: Tree) = unsplice(tree) match { case Apply(fn, _ :: _) => unsplice(fn) match { @@ -583,6 +571,16 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] => accum(Nil, root) } + /** The largest subset of {NoInits, PureInterface} that a + * trait enclosing this statement can have as flags. + */ + def defKind(tree: Tree): FlagSet = unsplice(tree) match { + case EmptyTree | _: Import => NoInitsInterface + case tree: TypeDef => if (tree.isClassDef) NoInits else NoInitsInterface + case tree: DefDef => if (tree.unforcedRhs == EmptyTree) NoInitsInterface else NoInits + case tree: ValDef => if (tree.unforcedRhs == EmptyTree) NoInitsInterface else EmptyFlags + case _ => EmptyFlags + } /** The top level classes in this tree, including only those module classes that * are not a linked class of some other class in the result. diff --git a/compiler/src/dotty/tools/dotc/ast/untpd.scala b/compiler/src/dotty/tools/dotc/ast/untpd.scala index 99bc3240f..8ca91590f 100644 --- a/compiler/src/dotty/tools/dotc/ast/untpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/untpd.scala @@ -149,6 +149,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { def is(fs: FlagSet): Boolean = flags is fs def is(fc: FlagConjunction): Boolean = flags is fc + def is(fc: FlagSet, butNot: FlagSet): Boolean = flags.is(fc, butNot = butNot) def | (fs: FlagSet): Modifiers = withFlags(flags | fs) def & (fs: FlagSet): Modifiers = withFlags(flags & fs) diff --git a/compiler/src/dotty/tools/dotc/config/Config.scala b/compiler/src/dotty/tools/dotc/config/Config.scala index 119af9483..dc56ad8b8 100644 --- a/compiler/src/dotty/tools/dotc/config/Config.scala +++ b/compiler/src/dotty/tools/dotc/config/Config.scala @@ -75,6 +75,15 @@ object Config { /** If this flag is set, take the fast path when comparing same-named type-aliases and types */ final val fastPathForRefinedSubtype = true + /** If this flag is set, and we compute `T1 { X = S1 }` & `T2 { X = S2 }` as a new + * upper bound of a constrained parameter, try to align the refinements by computing + * `S1 =:= S2` (which might instantiate type parameters). + * This rule is contentious because it cuts the constraint set. + * + * For more info, see the comment in `TypeComparer#distributeAnd`. + */ + final val alignArgsInAnd = true + /** If this flag is set, higher-kinded applications are checked for validity */ final val checkHKApplications = false diff --git a/compiler/src/dotty/tools/dotc/config/Settings.scala b/compiler/src/dotty/tools/dotc/config/Settings.scala index 58fa6d366..06ad2b84d 100644 --- a/compiler/src/dotty/tools/dotc/config/Settings.scala +++ b/compiler/src/dotty/tools/dotc/config/Settings.scala @@ -3,7 +3,6 @@ package config import collection.mutable.{ ArrayBuffer } import scala.util.{ Try, Success, Failure } -import scala.reflect.internal.util.StringOps import reflect.ClassTag import core.Contexts._ // import annotation.unchecked diff --git a/compiler/src/dotty/tools/dotc/core/Constraint.scala b/compiler/src/dotty/tools/dotc/core/Constraint.scala index c99b748b7..50136a26c 100644 --- a/compiler/src/dotty/tools/dotc/core/Constraint.scala +++ b/compiler/src/dotty/tools/dotc/core/Constraint.scala @@ -111,12 +111,6 @@ abstract class Constraint extends Showable { */ def replace(param: PolyParam, tp: Type)(implicit ctx: Context): This - /** Narrow one of the bounds of type parameter `param` - * If `isUpper` is true, ensure that `param <: `bound`, otherwise ensure - * that `param >: bound`. - */ - def narrowBound(param: PolyParam, bound: Type, isUpper: Boolean)(implicit ctx: Context): This - /** Is entry associated with `pt` removable? This is the case if * all type parameters of the entry are associated with type variables * which have their `inst` fields set. diff --git a/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala b/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala index b3c50fb71..2a1f4ee6e 100644 --- a/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala +++ b/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala @@ -44,6 +44,13 @@ trait ConstraintHandling { try op finally alwaysFluid = saved } + /** If set, align arguments `S1`, `S2`when taking the glb + * `T1 { X = S1 } & T2 { X = S2 }` of a constraint upper bound for some type parameter. + * Aligning means computing `S1 =:= S2` which may change the current constraint. + * See note in TypeComparer#distributeAnd. + */ + protected var homogenizeArgs = false + /** We are currently comparing polytypes. Used as a flag for * optimization: when `false`, no need to do an expensive `pruneLambdaParams` */ @@ -64,7 +71,8 @@ trait ConstraintHandling { } if (Config.checkConstraintsSeparated) assert(!occursIn(bound), s"$param occurs in $bound") - val c1 = constraint.narrowBound(param, bound, isUpper) + val newBound = narrowedBound(param, bound, isUpper) + val c1 = constraint.updateEntry(param, newBound) (c1 eq constraint) || { constraint = c1 val TypeBounds(lo, hi) = constraint.entry(param) @@ -72,6 +80,20 @@ trait ConstraintHandling { } } + /** Narrow one of the bounds of type parameter `param` + * If `isUpper` is true, ensure that `param <: `bound`, otherwise ensure + * that `param >: bound`. + */ + def narrowedBound(param: PolyParam, bound: Type, isUpper: Boolean)(implicit ctx: Context): TypeBounds = { + val oldBounds @ TypeBounds(lo, hi) = constraint.nonParamBounds(param) + val saved = homogenizeArgs + homogenizeArgs = Config.alignArgsInAnd + try + if (isUpper) oldBounds.derivedTypeBounds(lo, hi & bound) + else oldBounds.derivedTypeBounds(lo | bound, hi) + finally homogenizeArgs = saved + } + protected def addUpperBound(param: PolyParam, bound: Type): Boolean = { def description = i"constraint $param <: $bound to\n$constraint" if (bound.isRef(defn.NothingClass) && ctx.typerState.isGlobalCommittable) { diff --git a/compiler/src/dotty/tools/dotc/core/Decorators.scala b/compiler/src/dotty/tools/dotc/core/Decorators.scala index a105741f5..f8267072e 100644 --- a/compiler/src/dotty/tools/dotc/core/Decorators.scala +++ b/compiler/src/dotty/tools/dotc/core/Decorators.scala @@ -15,12 +15,22 @@ import printing.Formatting._ object Decorators { /** Turns Strings into PreNames, adding toType/TermName methods */ - implicit class StringDecorator(val s: String) extends AnyVal with PreName { + implicit class PreNamedString(val s: String) extends AnyVal with PreName { def toTypeName: TypeName = typeName(s) def toTermName: TermName = termName(s) def toText(printer: Printer): Text = Str(s) } + implicit class StringDecorator(val s: String) extends AnyVal { + def splitWhere(f: Char => Boolean, doDropIndex: Boolean): Option[(String, String)] = { + def splitAt(idx: Int, doDropIndex: Boolean): Option[(String, String)] = + if (idx == -1) None + else Some((s.take(idx), s.drop(if (doDropIndex) idx + 1 else idx))) + + splitAt(s.indexWhere(f), doDropIndex) + } + } + /** Implements a findSymbol method on iterators of Symbols that * works like find but avoids Option, replacing None with NoSymbol. */ diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala index 79e97becb..4d4350f98 100644 --- a/compiler/src/dotty/tools/dotc/core/Definitions.scala +++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala @@ -10,7 +10,6 @@ import scala.collection.{ mutable, immutable } import PartialFunction._ import collection.mutable import util.common.alwaysZero -import scala.reflect.api.{ Universe => ApiUniverse } object Definitions { @@ -300,6 +299,8 @@ class Definitions { lazy val ScalaPredefModuleRef = ctx.requiredModuleRef("scala.Predef") def ScalaPredefModule(implicit ctx: Context) = ScalaPredefModuleRef.symbol + lazy val Predef_ConformsR = ScalaPredefModule.requiredClass("$less$colon$less").typeRef + def Predef_Conforms(implicit ctx: Context) = Predef_ConformsR.symbol lazy val Predef_conformsR = ScalaPredefModule.requiredMethodRef("$conforms") def Predef_conforms(implicit ctx: Context) = Predef_conformsR.symbol lazy val Predef_classOfR = ScalaPredefModule.requiredMethodRef("classOf") @@ -337,6 +338,8 @@ class Definitions { def DottyPredefModule(implicit ctx: Context) = DottyPredefModuleRef.symbol def Predef_eqAny(implicit ctx: Context) = DottyPredefModule.requiredMethod(nme.eqAny) + lazy val Predef_ImplicitConverterR = DottyPredefModule.requiredClass("ImplicitConverter").typeRef + def Predef_ImplicitConverter(implicit ctx: Context) = Predef_ImplicitConverterR.symbol lazy val DottyArraysModuleRef = ctx.requiredModuleRef("dotty.runtime.Arrays") def DottyArraysModule(implicit ctx: Context) = DottyArraysModuleRef.symbol @@ -352,6 +355,7 @@ class Definitions { enterCompleteClassSymbol( ScalaPackageClass, tpnme.Singleton, PureInterfaceCreationFlags | Final, List(AnyClass.typeRef), EmptyScope) + def SingletonType = SingletonClass.typeRef lazy val SeqType: TypeRef = ctx.requiredClassRef("scala.collection.Seq") def SeqClass(implicit ctx: Context) = SeqType.symbol.asClass diff --git a/compiler/src/dotty/tools/dotc/core/Flags.scala b/compiler/src/dotty/tools/dotc/core/Flags.scala index d2a1c58f5..c1267d8a2 100644 --- a/compiler/src/dotty/tools/dotc/core/Flags.scala +++ b/compiler/src/dotty/tools/dotc/core/Flags.scala @@ -287,9 +287,10 @@ object Flags { /** A trait that has only abstract methods as members - * (and therefore can be represented by a Java interface + * and therefore can be represented by a Java interface. + * Warning: flag is set during regular typer pass, should be tested only after typer. */ - final val PureInterface = typeFlag(22, "interface") // TODO when unpickling, reconstitute from context + final val PureInterface = typeFlag(22, "interface") /** Labeled with of abstract & override */ final val AbsOverride = termFlag(22, "abstract override") @@ -338,7 +339,9 @@ object Flags { final val JavaStaticTerm = JavaStatic.toTermFlags final val JavaStaticType = JavaStatic.toTypeFlags - /** Trait does not have fields or initialization code */ + /** Trait does not have fields or initialization code. + * Warning: flag is set during regular typer pass, should be tested only after typer. + */ final val NoInits = typeFlag(32, "<noInits>") /** Variable is accessed from nested function. */ diff --git a/compiler/src/dotty/tools/dotc/core/NameOps.scala b/compiler/src/dotty/tools/dotc/core/NameOps.scala index aac313892..ea905c19f 100644 --- a/compiler/src/dotty/tools/dotc/core/NameOps.scala +++ b/compiler/src/dotty/tools/dotc/core/NameOps.scala @@ -5,7 +5,7 @@ import java.security.MessageDigest import scala.annotation.switch import scala.io.Codec import Names._, StdNames._, Contexts._, Symbols._, Flags._ -import Decorators.StringDecorator +import Decorators.PreNamedString import util.{Chars, NameTransformer} import Chars.isOperatorPart import Definitions._ diff --git a/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala b/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala index 72c7a8e51..61dd5a445 100644 --- a/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala +++ b/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala @@ -354,14 +354,6 @@ class OrderingConstraint(private val boundsMap: ParamBounds, updateEntry(p1, p1Bounds).replace(p2, p1) } - def narrowBound(param: PolyParam, bound: Type, isUpper: Boolean)(implicit ctx: Context): This = { - val oldBounds @ TypeBounds(lo, hi) = nonParamBounds(param) - val newBounds = - if (isUpper) oldBounds.derivedTypeBounds(lo, hi & bound) - else oldBounds.derivedTypeBounds(lo | bound, hi) - updateEntry(param, newBounds) - } - // ---------- Removals ------------------------------------------------------------ /** A new constraint which is derived from this constraint by removing diff --git a/compiler/src/dotty/tools/dotc/core/StdNames.scala b/compiler/src/dotty/tools/dotc/core/StdNames.scala index 1e36361f8..5b7dc3d1d 100644 --- a/compiler/src/dotty/tools/dotc/core/StdNames.scala +++ b/compiler/src/dotty/tools/dotc/core/StdNames.scala @@ -7,7 +7,7 @@ import scala.annotation.switch import Names._ import Symbols._ import Contexts._ -import Decorators.StringDecorator +import Decorators.PreNamedString import util.NameTransformer import scala.collection.breakOut @@ -97,6 +97,7 @@ object StdNames { val EMPTY: N = "" val EMPTY_PACKAGE: N = Names.EMPTY_PACKAGE.toString val EVIDENCE_PARAM_PREFIX: N = "evidence$" + val DEP_PARAM_PREFIX = "<param>" val EXCEPTION_RESULT_PREFIX: N = "exceptionResult" val EXPAND_SEPARATOR: N = "$$" val IMPL_CLASS_SUFFIX: N = "$class" diff --git a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala index 9b9caf8e7..c98b444d9 100644 --- a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala @@ -158,7 +158,7 @@ object SymDenotations { final def resetFlag(flags: FlagSet): Unit = { myFlags &~= flags } /** Set applicable flags from `flags` which is a subset of {NoInits, PureInterface} */ - final def setApplicableFlags(flags: FlagSet): Unit = { + final def setNoInitsFlags(flags: FlagSet): Unit = { val mask = if (myFlags.is(Trait)) NoInitsInterface else NoInits setFlag(flags & mask) } diff --git a/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala b/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala index 4ae28c10b..79f8a6a45 100644 --- a/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala +++ b/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala @@ -12,7 +12,7 @@ import scala.compat.Platform.currentTime import dotty.tools.io.{ ClassPath, AbstractFile } import Contexts._, Symbols._, Flags._, SymDenotations._, Types._, Scopes._, util.Positions._, Names._ import StdNames._, NameOps._ -import Decorators.{StringDecorator, StringInterpolators} +import Decorators.{PreNamedString, StringInterpolators} import classfile.ClassfileParser import scala.util.control.NonFatal diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala index b97dfe684..b61fccf31 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala @@ -1300,23 +1300,28 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { case tp1: RefinedType => tp2 match { case tp2: RefinedType if tp1.refinedName == tp2.refinedName => - // Given two refinements `T1 { X = S1 }` and `T2 { X = S2 }`, if `S1 =:= S2` - // (possibly by instantiating type parameters), rewrite to `T1 & T2 { X = S1 }`. - // Otherwise rewrite to `T1 & T2 { X B }` where `B` is the conjunction of - // the bounds of `X` in `T1` and `T2`. - // The first rule above is contentious because it cuts the constraint set. - // But without it we would replace the two aliases by - // `T { X >: S1 | S2 <: S1 & S2 }`, which looks weird and is probably - // not what's intended. + // Given two refinements `T1 { X = S1 }` and `T2 { X = S2 }` rewrite to + // `T1 & T2 { X B }` where `B` is the conjunction of the bounds of `X` in `T1` and `T2`. + // + // However, if `homogenizeArgs` is set, and both aliases `X = Si` are + // nonvariant, and `S1 =:= S2` (possibly by instantiating type parameters), + // rewrite instead to `T1 & T2 { X = S1 }`. This rule is contentious because + // it cuts the constraint set. On the other hand, without it we would replace + // the two aliases by `T { X >: S1 | S2 <: S1 & S2 }`, which looks weird + // and is probably not what's intended. val rinfo1 = tp1.refinedInfo val rinfo2 = tp2.refinedInfo val parent = tp1.parent & tp2.parent - val rinfo = - if (rinfo1.isAlias && rinfo2.isAlias && isSameType(rinfo1, rinfo2)) - rinfo1 - else - rinfo1 & rinfo2 - tp1.derivedRefinedType(parent, tp1.refinedName, rinfo) + + def isNonvariantAlias(tp: Type) = tp match { + case tp: TypeAlias => tp.variance == 0 + case _ => false + } + if (homogenizeArgs && + isNonvariantAlias(rinfo1) && isNonvariantAlias(rinfo2)) + isSameType(rinfo1, rinfo2) // establish new constraint + + tp1.derivedRefinedType(parent, tp1.refinedName, rinfo1 & rinfo2) case _ => NoType } diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 070a6ea83..b8f81f1bb 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -19,6 +19,7 @@ import util.Positions.{Position, NoPosition} import util.Stats._ import util.{DotClass, SimpleMap} import reporting.diagnostic.Message +import reporting.diagnostic.messages.CyclicReferenceInvolving import ast.tpd._ import ast.TreeTypeMap import printing.Texts._ @@ -1684,7 +1685,10 @@ object Types { } else newLikeThis(prefix) } - else newLikeThis(prefix) + else prefix match { + case _: WildcardType => WildcardType + case _ => newLikeThis(prefix) + } /** Create a NamedType of the same kind as this type, but with a new prefix. */ @@ -3852,7 +3856,7 @@ object Types { class CyclicReference private (val denot: SymDenotation) extends TypeError(s"cyclic reference involving $denot") { - def show(implicit ctx: Context) = s"cyclic reference involving ${denot.show}" + def toMessage(implicit ctx: Context) = CyclicReferenceInvolving(denot) } object CyclicReference { diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index fcba957c0..fdb8a97ae 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -768,7 +768,7 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, posUnpickle } else EmptyValDef setClsInfo(parentRefs, if (self.isEmpty) NoType else self.tpt.tpe) - cls.setApplicableFlags(fork.indexStats(end)) + cls.setNoInitsFlags(fork.indexStats(end)) val constr = readIndexedDef().asInstanceOf[DefDef] def mergeTypeParamsAndAliases(tparams: List[TypeDef], stats: List[Tree])(implicit ctx: Context): (List[Tree], List[Tree]) = diff --git a/compiler/src/dotty/tools/dotc/core/unpickleScala2/PickleBuffer.scala b/compiler/src/dotty/tools/dotc/core/unpickleScala2/PickleBuffer.scala index 17fef3852..6ee9f1f9e 100644 --- a/compiler/src/dotty/tools/dotc/core/unpickleScala2/PickleBuffer.scala +++ b/compiler/src/dotty/tools/dotc/core/unpickleScala2/PickleBuffer.scala @@ -193,24 +193,7 @@ object PickleBuffer { private type FlagMap = Array[Array[Long]] private val (scalaTermFlagMap, scalaTypeFlagMap) = { - import scala.reflect.internal.Flags._ - - // The following vals are copy-pasted from reflect.internal.Flags. - // They are unfortunately private there, so we cannot get at them directly. - // Using the public method pickledToRawFlags instead looks unattractive - // because of performance. - val IMPLICIT_PKL = (1 << 0) - val FINAL_PKL = (1 << 1) - val PRIVATE_PKL = (1 << 2) - val PROTECTED_PKL = (1 << 3) - val SEALED_PKL = (1 << 4) - val OVERRIDE_PKL = (1 << 5) - val CASE_PKL = (1 << 6) - val ABSTRACT_PKL = (1 << 7) - val DEFERRED_PKL = (1 << 8) - val METHOD_PKL = (1 << 9) - val MODULE_PKL = (1 << 10) - val INTERFACE_PKL = (1 << 11) + import Scala2Flags._ val corr = Map( PROTECTED_PKL -> Protected, diff --git a/compiler/src/dotty/tools/dotc/core/unpickleScala2/PickleFormat.scala b/compiler/src/dotty/tools/dotc/core/unpickleScala2/PickleFormat.scala new file mode 100644 index 000000000..a8855545f --- /dev/null +++ b/compiler/src/dotty/tools/dotc/core/unpickleScala2/PickleFormat.scala @@ -0,0 +1,227 @@ +package dotty.tools +package dotc +package core +package unpickleScala2 + +/** This object provides constants for pickling attributes. + * + * If you extend the format, be sure to increase the + * version minor number. + * + * This was adapted from https://github.com/scala/scala/blob/2.11.x/src/reflect/scala/reflect/internal/pickling/PickleFormat.scala + * + * @author Martin Odersky + * @version 1.0 + */ +object PickleFormat { + +/*************************************************** + * Symbol table attribute format: + * Symtab = nentries_Nat {Entry} + * Entry = 1 TERMNAME len_Nat NameInfo + * | 2 TYPENAME len_Nat NameInfo + * | 3 NONEsym len_Nat + * | 4 TYPEsym len_Nat SymbolInfo + * | 5 ALIASsym len_Nat SymbolInfo + * | 6 CLASSsym len_Nat SymbolInfo [thistype_Ref] + * | 7 MODULEsym len_Nat SymbolInfo + * | 8 VALsym len_Nat [defaultGetter_Ref /* no longer needed*/] SymbolInfo [alias_Ref] + * | 9 EXTref len_Nat name_Ref [owner_Ref] + * | 10 EXTMODCLASSref len_Nat name_Ref [owner_Ref] + * | 11 NOtpe len_Nat + * | 12 NOPREFIXtpe len_Nat + * | 13 THIStpe len_Nat sym_Ref + * | 14 SINGLEtpe len_Nat type_Ref sym_Ref + * | 15 CONSTANTtpe len_Nat constant_Ref + * | 16 TYPEREFtpe len_Nat type_Ref sym_Ref {targ_Ref} + * | 17 TYPEBOUNDStpe len_Nat tpe_Ref tpe_Ref + * | 18 REFINEDtpe len_Nat classsym_Ref {tpe_Ref} + * | 19 CLASSINFOtpe len_Nat classsym_Ref {tpe_Ref} + * | 20 METHODtpe len_Nat tpe_Ref {sym_Ref} + * | 21 POLYTtpe len_Nat tpe_Ref {sym_Ref} + * | 22 IMPLICITMETHODtpe len_Nat tpe_Ref {sym_Ref} /* no longer needed */ + * | 52 SUPERtpe len_Nat tpe_Ref tpe_Ref + * | 24 LITERALunit len_Nat + * | 25 LITERALboolean len_Nat value_Long + * | 26 LITERALbyte len_Nat value_Long + * | 27 LITERALshort len_Nat value_Long + * | 28 LITERALchar len_Nat value_Long + * | 29 LITERALint len_Nat value_Long + * | 30 LITERALlong len_Nat value_Long + * | 31 LITERALfloat len_Nat value_Long + * | 32 LITERALdouble len_Nat value_Long + * | 33 LITERALstring len_Nat name_Ref + * | 34 LITERALnull len_Nat + * | 35 LITERALclass len_Nat tpe_Ref + * | 36 LITERALenum len_Nat sym_Ref + * | 40 SYMANNOT len_Nat sym_Ref AnnotInfoBody + * | 41 CHILDREN len_Nat sym_Ref {sym_Ref} + * | 42 ANNOTATEDtpe len_Nat [sym_Ref /* no longer needed */] tpe_Ref {annotinfo_Ref} + * | 43 ANNOTINFO len_Nat AnnotInfoBody + * | 44 ANNOTARGARRAY len_Nat {constAnnotArg_Ref} + * | 47 DEBRUIJNINDEXtpe len_Nat level_Nat index_Nat /* no longer needed */ + * | 48 EXISTENTIALtpe len_Nat type_Ref {symbol_Ref} + * | 49 TREE len_Nat 1 EMPTYtree + * | 49 TREE len_Nat 2 PACKAGEtree type_Ref sym_Ref mods_Ref name_Ref {tree_Ref} + * | 49 TREE len_Nat 3 CLASStree type_Ref sym_Ref mods_Ref name_Ref tree_Ref {tree_Ref} + * | 49 TREE len_Nat 4 MODULEtree type_Ref sym_Ref mods_Ref name_Ref tree_Ref + * | 49 TREE len_Nat 5 VALDEFtree type_Ref sym_Ref mods_Ref name_Ref tree_Ref tree_Ref + * | 49 TREE len_Nat 6 DEFDEFtree type_Ref sym_Ref mods_Ref name_Ref numtparams_Nat {tree_Ref} numparamss_Nat {numparams_Nat {tree_Ref}} tree_Ref tree_Ref + * | 49 TREE len_Nat 7 TYPEDEFtree type_Ref sym_Ref mods_Ref name_Ref tree_Ref {tree_Ref} + * | 49 TREE len_Nat 8 LABELtree type_Ref sym_Ref tree_Ref {tree_Ref} + * | 49 TREE len_Nat 9 IMPORTtree type_Ref sym_Ref tree_Ref {name_Ref name_Ref} + * | 49 TREE len_Nat 11 DOCDEFtree type_Ref sym_Ref string_Ref tree_Ref + * | 49 TREE len_Nat 12 TEMPLATEtree type_Ref sym_Ref numparents_Nat {tree_Ref} tree_Ref {tree_Ref} + * | 49 TREE len_Nat 13 BLOCKtree type_Ref tree_Ref {tree_Ref} + * | 49 TREE len_Nat 14 CASEtree type_Ref tree_Ref tree_Ref tree_Ref + * | 49 TREE len_Nat 15 SEQUENCEtree type_Ref {tree_Ref} + * | 49 TREE len_Nat 16 ALTERNATIVEtree type_Ref {tree_Ref} + * | 49 TREE len_Nat 17 STARtree type_Ref {tree_Ref} + * | 49 TREE len_Nat 18 BINDtree type_Ref sym_Ref name_Ref tree_Ref + * | 49 TREE len_Nat 19 UNAPPLYtree type_Ref tree_Ref {tree_Ref} + * | 49 TREE len_Nat 20 ARRAYVALUEtree type_Ref tree_Ref {tree_Ref} + * | 49 TREE len_Nat 21 FUNCTIONtree type_Ref sym_Ref tree_Ref {tree_Ref} + * | 49 TREE len_Nat 22 ASSIGNtree type_Ref tree_Ref tree_Ref + * | 49 TREE len_Nat 23 IFtree type_Ref tree_Ref tree_Ref tree_Ref + * | 49 TREE len_Nat 24 MATCHtree type_Ref tree_Ref {tree_Ref} + * | 49 TREE len_Nat 25 RETURNtree type_Ref sym_Ref tree_Ref + * | 49 TREE len_Nat 26 TREtree type_Ref tree_Ref tree_Ref {tree_Ref} + * | 49 TREE len_Nat 27 THROWtree type_Ref tree_Ref + * | 49 TREE len_Nat 28 NEWtree type_Ref tree_Ref + * | 49 TREE len_Nat 29 TYPEDtree type_Ref tree_Ref tree_Ref + * | 49 TREE len_Nat 30 TYPEAPPLYtree type_Ref tree_Ref {tree_Ref} + * | 49 TREE len_Nat 31 APPLYtree type_Ref tree_Ref {tree_Ref} + * | 49 TREE len_Nat 32 APPLYDYNAMICtree type_Ref sym_Ref tree_Ref {tree_Ref} + * | 49 TREE len_Nat 33 SUPERtree type_Ref sym_Ref tree_Ref name_Ref + * | 49 TREE len_Nat 34 THIStree type_Ref sym_Ref name_Ref + * | 49 TREE len_Nat 35 SELECTtree type_Ref sym_Ref tree_Ref name_Ref + * | 49 TREE len_Nat 36 IDENTtree type_Ref sym_Ref name_Ref + * | 49 TREE len_Nat 37 LITERALtree type_Ref constant_Ref + * | 49 TREE len_Nat 38 TYPEtree type_Ref + * | 49 TREE len_Nat 39 ANNOTATEDtree type_Ref tree_Ref tree_Ref + * | 49 TREE len_Nat 40 SINGLETONTYPEtree type_Ref tree_Ref + * | 49 TREE len_Nat 41 SELECTFROMTYPEtree type_Ref tree_Ref name_Ref + * | 49 TREE len_Nat 42 COMPOUNDTYPEtree type_Ref tree_Ref + * | 49 TREE len_Nat 43 APPLIEDTYPEtree type_Ref tree_Ref {tree_Ref} + * | 49 TREE len_Nat 44 TYPEBOUNDStree type_Ref tree_Ref tree_Ref + * | 49 TREE len_Nat 45 EXISTENTIALTYPEtree type_Ref tree_Ref {tree_Ref} + * | 50 MODIFIERS len_Nat flags_Long privateWithin_Ref + * SymbolInfo = name_Ref owner_Ref flags_LongNat [privateWithin_Ref] info_Ref + * NameInfo = <character sequence of length len_Nat in Utf8 format> + * NumInfo = <len_Nat-byte signed number in big endian format> + * Ref = Nat + * AnnotInfoBody = info_Ref {annotArg_Ref} {name_Ref constAnnotArg_Ref} + * AnnotArg = Tree | Constant + * ConstAnnotArg = Constant | AnnotInfo | AnnotArgArray + * + * len is remaining length after `len`. + */ + val MajorVersion = 5 + val MinorVersion = 0 + + final val TERMname = 1 + final val TYPEname = 2 + final val NONEsym = 3 + final val TYPEsym = 4 + final val ALIASsym = 5 + final val CLASSsym = 6 + final val MODULEsym = 7 + final val VALsym = 8 + final val EXTref = 9 + final val EXTMODCLASSref = 10 + final val NOtpe = 11 + final val NOPREFIXtpe = 12 + final val THIStpe = 13 + final val SINGLEtpe = 14 + final val CONSTANTtpe = 15 + final val TYPEREFtpe = 16 + final val TYPEBOUNDStpe = 17 + final val REFINEDtpe = 18 + final val CLASSINFOtpe = 19 + final val METHODtpe = 20 + final val POLYtpe = 21 + final val IMPLICITMETHODtpe = 22 // no longer generated + + final val LITERAL = 23 // base line for literals + final val LITERALunit = 24 + final val LITERALboolean = 25 + final val LITERALbyte = 26 + final val LITERALshort = 27 + final val LITERALchar = 28 + final val LITERALint = 29 + final val LITERALlong = 30 + final val LITERALfloat = 31 + final val LITERALdouble = 32 + final val LITERALstring = 33 + final val LITERALnull = 34 + final val LITERALclass = 35 + final val LITERALenum = 36 + final val SYMANNOT = 40 + final val CHILDREN = 41 + final val ANNOTATEDtpe = 42 + final val ANNOTINFO = 43 + final val ANNOTARGARRAY = 44 + + final val SUPERtpe = 46 + final val DEBRUIJNINDEXtpe = 47 // no longer generated + final val EXISTENTIALtpe = 48 + + final val TREE = 49 // prefix code that means a tree is coming + final val EMPTYtree = 1 + final val PACKAGEtree = 2 + final val CLASStree = 3 + final val MODULEtree = 4 + final val VALDEFtree = 5 + final val DEFDEFtree = 6 + final val TYPEDEFtree = 7 + final val LABELtree = 8 + final val IMPORTtree = 9 + final val DOCDEFtree = 11 + final val TEMPLATEtree = 12 + final val BLOCKtree = 13 + final val CASEtree = 14 + // This node type has been removed. + // final val SEQUENCEtree = 15 + final val ALTERNATIVEtree = 16 + final val STARtree = 17 + final val BINDtree = 18 + final val UNAPPLYtree = 19 + final val ARRAYVALUEtree = 20 + final val FUNCTIONtree = 21 + final val ASSIGNtree = 22 + final val IFtree = 23 + final val MATCHtree = 24 + final val RETURNtree = 25 + final val TREtree = 26 + final val THROWtree = 27 + final val NEWtree = 28 + final val TYPEDtree = 29 + final val TYPEAPPLYtree = 30 + final val APPLYtree = 31 + final val APPLYDYNAMICtree = 32 + final val SUPERtree = 33 + final val THIStree = 34 + final val SELECTtree = 35 + final val IDENTtree = 36 + final val LITERALtree = 37 + final val TYPEtree = 38 + final val ANNOTATEDtree = 39 + final val SINGLETONTYPEtree = 40 + final val SELECTFROMTYPEtree = 41 + final val COMPOUNDTYPEtree = 42 + final val APPLIEDTYPEtree = 43 + final val TYPEBOUNDStree = 44 + final val EXISTENTIALTYPEtree = 45 + + final val MODIFIERS = 50 + + final val firstSymTag = NONEsym + final val lastSymTag = VALsym + final val lastExtSymTag = EXTMODCLASSref + + + //The following two are no longer accurate, because ANNOTATEDtpe, + //SUPERtpe, ... are not in the same range as the other types + //final val firstTypeTag = NOtpe + //final val lastTypeTag = POLYtpe +} diff --git a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Flags.scala b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Flags.scala new file mode 100644 index 000000000..97480e49f --- /dev/null +++ b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Flags.scala @@ -0,0 +1,109 @@ +/* NSC -- new Scala compiler + * Copyright 2005-2013 LAMP/EPFL + * @author Martin Odersky + */ + +package dotty.tools +package dotc +package core +package unpickleScala2 + +import scala.collection.{ mutable, immutable } + +/** Scala2 flags, adapted from https://github.com/scala/scala/blob/2.11.x/src/reflect/scala/reflect/internal/Flags.scala + */ +object Scala2Flags { + final val IMPLICIT = 1 << 9 + final val FINAL = 1 << 5 // May not be overridden. Note that java final implies much more than scala final. + final val PRIVATE = 1 << 2 + final val PROTECTED = 1 << 0 + + final val SEALED = 1 << 10 + final val OVERRIDE = 1 << 1 + final val CASE = 1 << 11 + final val ABSTRACT = 1 << 3 // abstract class, or used in conjunction with abstract override. + // Note difference to DEFERRED! + final val DEFERRED = 1 << 4 // was `abstract' for members | trait is virtual + final val INTERFACE = 1 << 7 // symbol is an interface (i.e. a trait which defines only abstract methods) + final val MUTABLE = 1 << 12 // symbol is a mutable variable. + final val PARAM = 1 << 13 // symbol is a (value or type) parameter to a method + final val MACRO = 1 << 15 // symbol is a macro definition + + final val COVARIANT = 1 << 16 // symbol is a covariant type variable + final val BYNAMEPARAM = 1 << 16 // parameter is by name + final val CONTRAVARIANT = 1 << 17 // symbol is a contravariant type variable + final val ABSOVERRIDE = 1 << 18 // combination of abstract & override + final val LOCAL = 1 << 19 // symbol is local to current class (i.e. private[this] or protected[this] + // pre: PRIVATE or PROTECTED are also set + final val JAVA = 1 << 20 // symbol was defined by a Java class + final val STATIC = 1 << 23 // static field, method or class + final val CASEACCESSOR = 1 << 24 // symbol is a case parameter (or its accessor, or a GADT skolem) + final val TRAIT = 1 << 25 // symbol is a trait + final val DEFAULTPARAM = 1 << 25 // the parameter has a default value + final val PARAMACCESSOR = 1 << 29 // for field definitions generated for primary constructor + // parameters (no matter if it's a 'val' parameter or not) + // for parameters of a primary constructor ('val' or not) + // for the accessor methods generated for 'val' or 'var' parameters + final val LAZY = 1L << 31 // symbol is a lazy val. can't have MUTABLE unless transformed by typer + final val PRESUPER = 1L << 37 // value is evaluated before super call + final val DEFAULTINIT = 1L << 41 // symbol is initialized to the default value: used by -Xcheckinit + final val ARTIFACT = 1L << 46 // symbol should be ignored when typechecking; will be marked ACC_SYNTHETIC in bytecode + // to see which symbols are marked as ARTIFACT, see scaladocs for FlagValues.ARTIFACT + final val DEFAULTMETHOD = 1L << 47 // symbol is a java default method + final val ENUM = 1L << 48 // symbol is an enum + + final val PrivateLocal = PRIVATE | LOCAL + final val ProtectedLocal = PROTECTED | LOCAL + final val AccessFlags = PRIVATE | PROTECTED | LOCAL + + final val METHOD = 1 << 6 // a method + final val MODULE = 1 << 8 // symbol is module or class implementing a module + final val PACKAGE = 1 << 14 // symbol is a java package + + final val CAPTURED = 1 << 16 // variable is accessed from nested function. Set by LambdaLift. + final val LABEL = 1 << 17 // method symbol is a label. Set by TailCall + final val INCONSTRUCTOR = 1 << 17 // class symbol is defined in this/superclass constructor. + final val SYNTHETIC = 1 << 21 // symbol is compiler-generated (compare with ARTIFACT) + final val STABLE = 1 << 22 // functions that are assumed to be stable + // (typically, access methods for valdefs) + // or classes that do not contain abstract types. + final val BRIDGE = 1 << 26 // function is a bridge method. Set by Erasure + final val ACCESSOR = 1 << 27 // a value or variable accessor (getter or setter) + + final val SUPERACCESSOR = 1 << 28 // a super accessor + final val MODULEVAR = 1 << 30 // for variables: is the variable caching a module value + + final val IS_ERROR = 1L << 32 // symbol is an error symbol + final val OVERLOADED = 1L << 33 // symbol is overloaded + final val LIFTED = 1L << 34 // class has been lifted out to package level + // local value has been lifted out to class level + // todo: make LIFTED = latePRIVATE? + 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 + final val SPECIALIZED = 1L << 40 // symbol is a generated specialized member + final val VBRIDGE = 1L << 42 // symbol is a varargs bridge + + final val VARARGS = 1L << 43 // symbol is a Java-style varargs method + final val TRIEDCOOKING = 1L << 44 // `Cooking` has been tried on this symbol + // A Java method's type is `cooked` by transforming raw types to existentials + + final val SYNCHRONIZED = 1L << 45 // symbol is a method which should be marked ACC_SYNCHRONIZED + + final val IMPLICIT_PKL = (1 << 0) + final val FINAL_PKL = (1 << 1) + final val PRIVATE_PKL = (1 << 2) + final val PROTECTED_PKL = (1 << 3) + final val SEALED_PKL = (1 << 4) + final val OVERRIDE_PKL = (1 << 5) + final val CASE_PKL = (1 << 6) + final val ABSTRACT_PKL = (1 << 7) + final val DEFERRED_PKL = (1 << 8) + final val METHOD_PKL = (1 << 9) + final val MODULE_PKL = (1 << 10) + final val INTERFACE_PKL = (1 << 11) +} diff --git a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala index 3a2a45fd2..faf01b177 100644 --- a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala @@ -19,7 +19,7 @@ import io.AbstractFile import util.common._ import typer.Checking.checkNonCyclic import PickleBuffer._ -import scala.reflect.internal.pickling.PickleFormat._ +import PickleFormat._ import Decorators._ import TypeApplications._ import classfile.ClassfileParser diff --git a/compiler/src/dotty/tools/dotc/parsing/CharArrayReader.scala b/compiler/src/dotty/tools/dotc/parsing/CharArrayReader.scala index b84e2eb47..e20eb392d 100644 --- a/compiler/src/dotty/tools/dotc/parsing/CharArrayReader.scala +++ b/compiler/src/dotty/tools/dotc/parsing/CharArrayReader.scala @@ -2,7 +2,7 @@ package dotty.tools package dotc package parsing -import scala.reflect.internal.Chars._ +import util.Chars._ abstract class CharArrayReader { self => diff --git a/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala b/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala index d35594823..6b73a9456 100644 --- a/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala @@ -26,7 +26,6 @@ import dotty.tools.dotc.util.SourceFile import util.Positions._ import annotation.switch import scala.collection.mutable.ListBuffer -import scala.reflect.internal.util.Collections._ object JavaParsers { @@ -136,7 +135,7 @@ object JavaParsers { ValDef(name, tpt, EmptyTree).withMods(Modifiers(Flags.JavaDefined | Flags.ParamAccessor)) def makeConstructor(formals: List[Tree], tparams: List[TypeDef], flags: FlagSet = Flags.JavaDefined) = { - val vparams = mapWithIndex(formals)((p, i) => makeSyntheticParam(i + 1, p)) + val vparams = formals.zipWithIndex.map { case (p, i) => makeSyntheticParam(i + 1, p) } DefDef(nme.CONSTRUCTOR, tparams, List(vparams), TypeTree(), EmptyTree).withMods(Modifiers(flags)) } diff --git a/compiler/src/dotty/tools/dotc/parsing/JavaScanners.scala b/compiler/src/dotty/tools/dotc/parsing/JavaScanners.scala index 83e16627c..9e0da2c05 100644 --- a/compiler/src/dotty/tools/dotc/parsing/JavaScanners.scala +++ b/compiler/src/dotty/tools/dotc/parsing/JavaScanners.scala @@ -7,7 +7,7 @@ import Scanners._ import util.SourceFile import JavaTokens._ import scala.annotation.{ switch, tailrec } -import scala.reflect.internal.Chars._ +import util.Chars._ object JavaScanners { diff --git a/compiler/src/dotty/tools/dotc/parsing/MarkupParserCommon.scala b/compiler/src/dotty/tools/dotc/parsing/MarkupParserCommon.scala index ce2c41797..492a8947c 100644 --- a/compiler/src/dotty/tools/dotc/parsing/MarkupParserCommon.scala +++ b/compiler/src/dotty/tools/dotc/parsing/MarkupParserCommon.scala @@ -9,7 +9,7 @@ package dotty.tools.dotc package parsing import Utility._ -import scala.reflect.internal.Chars.SU +import util.Chars.SU diff --git a/compiler/src/dotty/tools/dotc/parsing/MarkupParsers.scala b/compiler/src/dotty/tools/dotc/parsing/MarkupParsers.scala index f648b9e2c..3b091d542 100644 --- a/compiler/src/dotty/tools/dotc/parsing/MarkupParsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/MarkupParsers.scala @@ -5,7 +5,7 @@ package parsing import scala.collection.mutable import mutable.{ Buffer, ArrayBuffer, ListBuffer } import scala.util.control.ControlThrowable -import scala.reflect.internal.Chars.SU +import util.Chars.SU import Parsers._ import util.Positions._ import core._ diff --git a/compiler/src/dotty/tools/dotc/parsing/Scanners.scala b/compiler/src/dotty/tools/dotc/parsing/Scanners.scala index b75169792..847f600c0 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Scanners.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Scanners.scala @@ -6,7 +6,7 @@ import core.Names._, core.Contexts._, core.Decorators._, util.Positions._ import core.StdNames._, core.Comments._ import util.SourceFile import java.lang.Character.isDigit -import scala.reflect.internal.Chars._ +import util.Chars._ import Tokens._ import scala.annotation.{ switch, tailrec } import scala.collection.mutable diff --git a/compiler/src/dotty/tools/dotc/parsing/SymbolicXMLBuilder.scala b/compiler/src/dotty/tools/dotc/parsing/SymbolicXMLBuilder.scala index 09d1b20b1..c99826488 100644 --- a/compiler/src/dotty/tools/dotc/parsing/SymbolicXMLBuilder.scala +++ b/compiler/src/dotty/tools/dotc/parsing/SymbolicXMLBuilder.scala @@ -5,12 +5,12 @@ package parsing import scala.collection.mutable import scala.xml.{ EntityRef, Text } import core._ +import Decorators._ import Flags.Mutable import Names._, StdNames._, ast.Trees._, ast.{tpd, untpd} import Symbols._, Contexts._ import util.Positions._ import Parsers.Parser -import scala.reflect.internal.util.StringOps.splitWhere import scala.language.implicitConversions /** This class builds instance of `Tree` that represent XML. @@ -171,7 +171,7 @@ class SymbolicXMLBuilder(parser: Parser, preserveWS: Boolean)(implicit ctx: Cont } /** Returns (Some(prefix) | None, rest) based on position of ':' */ - def splitPrefix(name: String): (Option[String], String) = splitWhere(name, _ == ':', true) match { + def splitPrefix(name: String): (Option[String], String) = name.splitWhere(_ == ':', doDropIndex = true) match { case Some((pre, rest)) => (Some(pre), rest) case _ => (None, name) } diff --git a/compiler/src/dotty/tools/dotc/parsing/Utility.scala b/compiler/src/dotty/tools/dotc/parsing/Utility.scala index f522492f8..8af594d68 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Utility.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Utility.scala @@ -1,4 +1,5 @@ -package dotty.tools.dotc.parsing +package dotty.tools.dotc +package parsing import scala.collection.mutable @@ -10,7 +11,7 @@ import scala.collection.mutable * @author Burak Emir */ object Utility { - import scala.reflect.internal.Chars.SU + import util.Chars.SU private val unescMap = Map( "lt" -> '<', diff --git a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala index 0d1068b8c..6af902d1b 100644 --- a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala @@ -4,6 +4,7 @@ package printing import core._ import Texts._, Types._, Flags._, Names._, Symbols._, NameOps._, Constants._, Denotations._ import Contexts.Context, Scopes.Scope, Denotations.Denotation, Annotations.Annotation +import TypeApplications.AppliedType import StdNames.{nme, tpnme} import ast.Trees._, ast._ import typer.Implicits._ @@ -119,10 +120,11 @@ class PlainPrinter(_ctx: Context) extends Printer { } /** The longest sequence of refinement types, starting at given type - * and following parents. + * and following parents, but stopping at applied types. */ private def refinementChain(tp: Type): List[Type] = tp :: (tp match { + case AppliedType(_, _) => Nil case tp: RefinedType => refinementChain(tp.parent.stripTypeVar) case _ => Nil }) diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java b/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java index a530a937f..7b56c8ed4 100644 --- a/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java +++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java @@ -51,6 +51,10 @@ public enum ErrorMessageID { MixedLeftAndRightAssociativeOpsID, CantInstantiateAbstractClassOrTraitID, AnnotatedPrimaryConstructorRequiresModifierOrThisID, + OverloadedOrRecursiveMethodNeedsResultTypeID, + RecursiveValueNeedsResultTypeID, + CyclicReferenceInvolvingID, + CyclicReferenceInvolvingImplicitID, ; public int errorNumber() { diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala index 54090074a..4c53fa496 100644 --- a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala @@ -18,6 +18,7 @@ import dotc.parsing.Tokens import printing.Highlighting._ import printing.Formatting import ErrorMessageID._ +import dotty.tools.dotc.core.SymDenotations.SymDenotation object messages { @@ -1134,7 +1135,7 @@ object messages { } case class AnnotatedPrimaryConstructorRequiresModifierOrThis(cls: Name)(implicit ctx: Context) - extends Message(AnnotatedPrimaryConstructorRequiresModifierOrThisID) { + extends Message(AnnotatedPrimaryConstructorRequiresModifierOrThisID) { val kind = "Syntax" val msg = hl"""${"private"}, ${"protected"}, or ${"this"} expected for annotated primary constructor""" val explanation = @@ -1147,4 +1148,48 @@ object messages { | ^^^^ |""".stripMargin } + + case class OverloadedOrRecursiveMethodNeedsResultType(tree: Names.TermName)(implicit ctx: Context) + extends Message(OverloadedOrRecursiveMethodNeedsResultTypeID) { + val kind = "Syntax" + val msg = hl"""overloaded or recursive method ${tree} needs return type""" + val explanation = + hl"""Case 1: ${tree} is overloaded + |If there are multiple methods named `${tree.name}` and at least one definition of + |it calls another, you need to specify the calling method's return type. + | + |Case 2: ${tree} is recursive + |If `${tree.name}` calls itself on any path, you need to specify its return type. + |""".stripMargin + } + + case class RecursiveValueNeedsResultType(tree: Names.TermName)(implicit ctx: Context) + extends Message(RecursiveValueNeedsResultTypeID) { + val kind = "Syntax" + val msg = hl"""recursive value ${tree.name} needs type""" + val explanation = + hl"""The definition of `${tree.name}` is recursive and you need to specify its type. + |""".stripMargin + } + + case class CyclicReferenceInvolving(denot: SymDenotation)(implicit ctx: Context) + extends Message(CyclicReferenceInvolvingID) { + val kind = "Syntax" + val msg = hl"""cyclic reference involving $denot""" + val explanation = + hl"""|$denot is declared as part of a cycle which makes it impossible for the + |compiler to decide upon ${denot.name}'s type. + |""".stripMargin + } + + case class CyclicReferenceInvolvingImplicit(cycleSym: Symbol)(implicit ctx: Context) + extends Message(CyclicReferenceInvolvingImplicitID) { + val kind = "Syntax" + val msg = hl"""cyclic reference involving implicit $cycleSym""" + val explanation = + hl"""|This happens when the right hand-side of $cycleSym's definition involves an implicit search. + |To avoid this error, give `${cycleSym.name}` an explicit type. + |""".stripMargin + } + } diff --git a/compiler/src/dotty/tools/dotc/transform/FullParameterization.scala b/compiler/src/dotty/tools/dotc/transform/FullParameterization.scala index 9e43fc999..5609817d8 100644 --- a/compiler/src/dotty/tools/dotc/transform/FullParameterization.scala +++ b/compiler/src/dotty/tools/dotc/transform/FullParameterization.scala @@ -12,8 +12,6 @@ import NameOps._ import ast._ import ast.Trees._ -import scala.reflect.internal.util.Collections - /** Provides methods to produce fully parameterized versions of instance methods, * where the `this` of the enclosing class is abstracted out in an extra leading * `$this` parameter and type parameters of the class become additional type @@ -234,8 +232,8 @@ trait FullParameterization { fun.appliedToArgss(originalDef.vparamss.nestedMap(vparam => ref(vparam.symbol))) else { // this type could have changed on forwarding. Need to insert a cast. - val args = Collections.map2(originalDef.vparamss, fun.tpe.paramTypess)((vparams, paramTypes) => - Collections.map2(vparams, paramTypes)((vparam, paramType) => { + val args = (originalDef.vparamss, fun.tpe.paramTypess).zipped.map((vparams, paramTypes) => + (vparams, paramTypes).zipped.map((vparam, paramType) => { assert(vparam.tpe <:< paramType.widen) // type should still conform to widened type ref(vparam.symbol).ensureConforms(paramType) }) diff --git a/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala b/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala index 7c49e68dd..7576ccc05 100644 --- a/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala +++ b/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala @@ -30,8 +30,6 @@ import dotty.tools.dotc.util.Positions.Position import dotty.tools.dotc.core.Decorators._ import dotty.tools.dotc.core.Flags -import scala.reflect.internal.util.Collections - /** This transform eliminates patterns. Right now it's a dummy. * Awaiting the real pattern matcher. * elimRepeated is required @@ -166,7 +164,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer { } def emitValDefs: List[ValDef] = { - Collections.map2(lhs, rhs)((symbol, tree) => ValDef(symbol.asTerm, tree.ensureConforms(symbol.info))) + (lhs, rhs).zipped.map((symbol, tree) => ValDef(symbol.asTerm, tree.ensureConforms(symbol.info))) } } object NoRebindings extends Rebindings(Nil, Nil) @@ -609,7 +607,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer { // only store binders actually used val (subPatBindersStored, subPatRefsStored) = stored.filter{case (b, _) => usedBinders(b)}.unzip - Block(Collections.map2(subPatBindersStored.toList, subPatRefsStored.toList)((bind, ref) => { + Block((subPatBindersStored.toList, subPatRefsStored.toList).zipped.map((bind, ref) => { // required in case original pattern had a more precise type // eg case s@"foo" => would be otherwise translated to s with type String instead of String("foo") def refTpeWiden = ref.tpe.widen diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index 222717e7e..a65ef00cc 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -213,16 +213,15 @@ trait Applications extends Compatibility { self: Typer with Dynamic => protected def init() = methType match { case methType: MethodType => // apply the result type constraint, unless method type is dependent - if (!methType.isDependent) { - val savedConstraint = ctx.typerState.constraint - if (!constrainResult(methType.resultType, resultType)) - if (ctx.typerState.isCommittable) - // defer the problem until after the application; - // it might be healed by an implicit conversion - assert(ctx.typerState.constraint eq savedConstraint) - else - fail(err.typeMismatchMsg(methType.resultType, resultType)) - } + val resultApprox = resultTypeApprox(methType) + val savedConstraint = ctx.typerState.constraint + if (!constrainResult(resultApprox, resultType)) + if (ctx.typerState.isCommittable) + // defer the problem until after the application; + // it might be healed by an implicit conversion + assert(ctx.typerState.constraint eq savedConstraint) + else + fail(err.typeMismatchMsg(methType.resultType, resultType)) // match all arguments with corresponding formal parameters matchArgs(orderedArgs, methType.paramTypes, 0) case _ => @@ -1100,10 +1099,8 @@ trait Applications extends Compatibility { self: Typer with Dynamic => /** Drop any implicit parameter section */ def stripImplicit(tp: Type): Type = tp match { - case mt: ImplicitMethodType if !mt.isDependent => - mt.resultType - // todo: make sure implicit method types are not dependent? - // but check test case in /tests/pos/depmet_implicit_chaining_zw.scala + case mt: ImplicitMethodType => + resultTypeApprox(mt) case pt: PolyType => pt.derivedPolyType(pt.paramNames, pt.paramBounds, stripImplicit(pt.resultType)) case _ => diff --git a/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala b/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala index 0978c2c1e..a1690955f 100644 --- a/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala +++ b/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala @@ -28,24 +28,22 @@ object ErrorReporting { def cyclicErrorMsg(ex: CyclicReference)(implicit ctx: Context) = { val cycleSym = ex.denot.symbol - def errorMsg(msg: String, cx: Context): String = + def errorMsg(msg: Message, cx: Context): Message = if (cx.mode is Mode.InferringReturnType) { cx.tree match { case tree: untpd.DefDef if !tree.tpt.typeOpt.exists => - em"overloaded or recursive method ${tree.name} needs result type" + OverloadedOrRecursiveMethodNeedsResultType(tree.name) case tree: untpd.ValDef if !tree.tpt.typeOpt.exists => - em"recursive value ${tree.name} needs type" + RecursiveValueNeedsResultType(tree.name) case _ => errorMsg(msg, cx.outer) } } else msg if (cycleSym.is(Implicit, butNot = Method) && cycleSym.owner.isTerm) - em"""cyclic reference involving implicit $cycleSym - |This happens when the right hand-side of $cycleSym's definition involves an implicit search. - |To avoid the error, give $cycleSym an explicit type.""" + CyclicReferenceInvolvingImplicit(cycleSym) else - errorMsg(ex.show, ctx) + errorMsg(ex.toMessage, ctx) } def wrongNumberOfTypeArgs(fntpe: Type, expectedArgs: List[TypeParamInfo], actual: List[untpd.Tree], pos: Position)(implicit ctx: Context) = diff --git a/compiler/src/dotty/tools/dotc/typer/Implicits.scala b/compiler/src/dotty/tools/dotc/typer/Implicits.scala index 759cc62e9..ebbcbcc95 100644 --- a/compiler/src/dotty/tools/dotc/typer/Implicits.scala +++ b/compiler/src/dotty/tools/dotc/typer/Implicits.scala @@ -82,11 +82,29 @@ object Implicits { case tpw: TermRef => false // can't discard overloaded refs case tpw => - //if (ctx.typer.isApplicable(tp, argType :: Nil, resultType)) - // println(i"??? $tp is applicable to $this / typeSymbol = ${tpw.typeSymbol}") - !tpw.derivesFrom(defn.FunctionClass(1)) || - ref.symbol == defn.Predef_conforms // - // as an implicit conversion, Predef.$conforms is a no-op, so exclude it + // Only direct instances of Function1 and direct or indirect instances of <:< are eligible as views. + // However, Predef.$conforms is not eligible, because it is a no-op. + // + // In principle, it would be cleanest if only implicit methods qualified + // as implicit conversions. We could achieve that by having standard conversions like + // this in Predef: + // + // implicit def convertIfConforms[A, B](x: A)(implicit ev: A <:< B): B = ev(a) + // implicit def convertIfConverter[A, B](x: A)(implicit ev: ImplicitConverter[A, B]): B = ev(a) + // + // (Once `<:<` inherits from `ImplicitConverter` we only need the 2nd one.) + // But clauses like this currently slow down implicit search a lot, because + // they are eligible for all pairs of types, and therefore are tried too often. + // We emulate instead these conversions directly in the search. + // The reason for leaving out `Predef_conforms` is that we know it adds + // nothing since it only relates subtype with supertype. + // + // We keep the old behavior under -language:Scala2. + val isFunctionInS2 = ctx.scala2Mode && tpw.derivesFrom(defn.FunctionClass(1)) + val isImplicitConverter = tpw.derivesFrom(defn.Predef_ImplicitConverter) + val isConforms = + tpw.derivesFrom(defn.Predef_Conforms) && ref.symbol != defn.Predef_conforms + !(isFunctionInS2 || isImplicitConverter || isConforms) } def discardForValueType(tpw: Type): Boolean = tpw match { diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala index 96660f15c..f2ad1f7c9 100644 --- a/compiler/src/dotty/tools/dotc/typer/Namer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala @@ -484,46 +484,91 @@ class Namer { typer: Typer => /** Create top-level symbols for statements and enter them into symbol table */ def index(stats: List[Tree])(implicit ctx: Context): Context = { - val classDef = mutable.Map[TypeName, TypeDef]() - val moduleDef = mutable.Map[TypeName, TypeDef]() + // module name -> (stat, moduleCls | moduleVal) + val moduleClsDef = mutable.Map[TypeName, (Tree, TypeDef)]() + val moduleValDef = mutable.Map[TermName, (Tree, ValDef)]() + + /** Remove the subtree `tree` from the expanded tree of `mdef` */ + def removeInExpanded(mdef: Tree, tree: Tree): Unit = { + val Thicket(trees) = expanded(mdef) + mdef.putAttachment(ExpandedTree, Thicket(trees.filter(_ != tree))) + } + + /** Merge the module class `modCls` in the expanded tree of `mdef` with the given stats */ + def mergeModuleClass(mdef: Tree, modCls: TypeDef, stats: List[Tree]): TypeDef = { + var res: TypeDef = null + val Thicket(trees) = expanded(mdef) + val merged = trees.map { tree => + if (tree == modCls) { + val impl = modCls.rhs.asInstanceOf[Template] + res = cpy.TypeDef(modCls)(rhs = cpy.Template(impl)(body = stats ++ impl.body)) + res + } + else tree + } + + mdef.putAttachment(ExpandedTree, Thicket(merged)) + + res + } + + /** Merge `fromCls` of `fromStat` into `toCls` of `toStat` + * if the former is synthetic and the latter not. + * + * Note: + * 1. `fromStat` and `toStat` could be the same stat + * 2. `fromCls` and `toCls` are necessarily different + */ + def mergeIfSynthetic(fromStat: Tree, fromCls: TypeDef, toStat: Tree, toCls: TypeDef): Unit = + if (fromCls.mods.is(Synthetic) && !toCls.mods.is(Synthetic)) { + removeInExpanded(fromStat, fromCls) + val mcls = mergeModuleClass(toStat, toCls, fromCls.rhs.asInstanceOf[Template].body) + moduleClsDef(fromCls.name) = (toStat, mcls) + } /** Merge the definitions of a synthetic companion generated by a case class * and the real companion, if both exist. */ def mergeCompanionDefs() = { - for (cdef @ TypeDef(name, _) <- stats) - if (cdef.isClassDef) { - classDef(name) = cdef - cdef.attachmentOrElse(ExpandedTree, cdef) match { - case Thicket(cls :: mval :: (mcls @ TypeDef(mname, _: Template)) :: crest) - if name.moduleClassName == mname => - moduleDef(name) = mcls - case _ => - } - } - for (mdef @ ModuleDef(name, _) <- stats if !mdef.mods.is(Flags.Package)) { - val typName = name.toTypeName - // Expansion of object is a flattened thicket with the first two elements being: - // module val :: module class :: rest - val Thicket(vdef :: (mcls @ TypeDef(_, impl: Template)) :: rest) = expanded(mdef) - moduleDef(typName) = mcls - classDef get name.toTypeName match { - case Some(cdef) => - cdef.attachmentOrElse(ExpandedTree, cdef) match { - case Thicket(cls :: mval :: TypeDef(mname, compimpl: Template) :: crest) - if name.moduleClassName == mname => - val mcls1 = cpy.TypeDef(mcls)( - rhs = cpy.Template(impl)(body = compimpl.body ++ impl.body)) - mdef.putAttachment(ExpandedTree, Thicket(vdef :: mcls1 :: rest)) - moduleDef(typName) = mcls1 - cdef.putAttachment(ExpandedTree, Thicket(cls :: crest)) + def valid(mdef: MemberDef): Boolean = mdef.mods.is(Module, butNot = Package) + + for (stat <- stats) + expanded(stat) match { + case Thicket(trees) => // companion object always expands to thickets + trees.map { + case mcls @ TypeDef(name, impl: Template) if valid(mcls) => + moduleClsDef.get(name) match { + case Some((stat1, mcls1@TypeDef(_, impl1: Template))) => + mergeIfSynthetic(stat, mcls, stat1, mcls1) + mergeIfSynthetic(stat1, mcls1, stat, mcls) + case None => + moduleClsDef(name) = (stat, mcls) + } + + case vdef @ ValDef(name, _, _) if valid(vdef) => + moduleValDef.get(name) match { + case Some((stat1, vdef1)) => + if (vdef.mods.is(Synthetic) && !vdef1.mods.is(Synthetic)) + removeInExpanded(stat, vdef) + else if (!vdef.mods.is(Synthetic) && vdef1.mods.is(Synthetic)) { + removeInExpanded(stat1, vdef1) + moduleValDef(name) = (stat, vdef) + } + else { + // double definition of objects or case classes, handled elsewhere + } + case None => + moduleValDef(name) = (stat, vdef) + } + case _ => } - case none => + case _ => + } - } } + /** Create links between companion object and companion class */ def createLinks(classTree: TypeDef, moduleTree: TypeDef)(implicit ctx: Context) = { val claz = ctx.denotNamed(classTree.name.encode).symbol val modl = ctx.denotNamed(moduleTree.name.encode).symbol @@ -532,8 +577,29 @@ class Namer { typer: Typer => } def createCompanionLinks(implicit ctx: Context): Unit = { + val classDef = mutable.Map[TypeName, TypeDef]() + val moduleDef = mutable.Map[TypeName, TypeDef]() + + def updateCache(cdef: TypeDef): Unit = { + if (!cdef.isClassDef || cdef.mods.is(Package)) return + + if (cdef.mods.is(ModuleClass)) moduleDef(cdef.name) = cdef + else classDef(cdef.name) = cdef + } + + for (stat <- stats) + expanded(stat) match { + case cdef : TypeDef => updateCache(cdef) + case Thicket(trees) => + trees.map { + case cdef: TypeDef => updateCache(cdef) + case _ => + } + case _ => + } + for (cdef @ TypeDef(name, _) <- classDef.values) { - moduleDef.getOrElse(name, EmptyTree) match { + moduleDef.getOrElse(name.moduleClassName, EmptyTree) match { case t: TypeDef => createLinks(cdef, t) case EmptyTree => @@ -818,8 +884,6 @@ class Namer { typer: Typer => Checking.checkWellFormed(cls) if (isDerivedValueClass(cls)) cls.setFlag(Final) - cls.setApplicableFlags( - (NoInitsInterface /: impl.body)((fs, stat) => fs & defKind(stat))) cls.info = avoidPrivateLeaks(cls, cls.pos) } } diff --git a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala index d666b563e..17f13d7c1 100644 --- a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala +++ b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala @@ -57,19 +57,14 @@ object ProtoTypes { case pt: FunProto => mt match { case mt: MethodType => - mt.isDependent || constrainResult(mt.resultType, pt.resultType) + constrainResult(resultTypeApprox(mt), pt.resultType) case _ => true } case _: ValueTypeOrProto if !disregardProto(pt) => - mt match { - case mt: MethodType => - mt.isDependent || isCompatible(normalize(mt, pt), pt) - case _ => - isCompatible(mt, pt) - } - case _: WildcardType => - isCompatible(mt, pt) + isCompatible(normalize(mt, pt), pt) + case pt: WildcardType if pt.optBounds.exists => + isCompatible(normalize(mt, pt), pt) case _ => true } @@ -394,6 +389,26 @@ object ProtoTypes { /** Same as `constrained(pt, EmptyTree)`, but returns just the created polytype */ def constrained(pt: PolyType)(implicit ctx: Context): PolyType = constrained(pt, EmptyTree)._1 + /** Create a new polyparam that represents a dependent method parameter singleton */ + def newDepPolyParam(tp: Type)(implicit ctx: Context): PolyParam = { + val poly = PolyType(ctx.freshName(nme.DEP_PARAM_PREFIX).toTypeName :: Nil, 0 :: Nil)( + pt => TypeBounds.upper(AndType(tp, defn.SingletonType)) :: Nil, + pt => defn.AnyType) + ctx.typeComparer.addToConstraint(poly, Nil) + PolyParam(poly, 0) + } + + /** The result type of `mt`, where all references to parameters of `mt` are + * replaced by either wildcards (if typevarsMissContext) or polyparams. + */ + def resultTypeApprox(mt: MethodType)(implicit ctx: Context): Type = + if (mt.isDependent) { + def replacement(tp: Type) = + if (ctx.mode.is(Mode.TypevarsMissContext)) WildcardType else newDepPolyParam(tp) + mt.resultType.substParams(mt, mt.paramTypes.map(replacement)) + } + else mt.resultType + /** The normalized form of a type * - unwraps polymorphic types, tracking their parameters in the current constraint * - skips implicit parameters; if result type depends on implicit parameter, @@ -413,22 +428,18 @@ object ProtoTypes { tp.widenSingleton match { case poly: PolyType => normalize(constrained(poly).resultType, pt) case mt: MethodType => - if (mt.isImplicit) - if (mt.isDependent) - mt.resultType.substParams(mt, mt.paramTypes.map(Function.const(WildcardType))) - else mt.resultType - else - if (mt.isDependent) tp - else { - val rt = normalize(mt.resultType, pt) + if (mt.isImplicit) resultTypeApprox(mt) + else if (mt.isDependent) tp + else { + val rt = normalize(mt.resultType, pt) pt match { case pt: IgnoredProto => mt case pt: ApplyingProto => mt.derivedMethodType(mt.paramNames, mt.paramTypes, rt) case _ => val ft = defn.FunctionOf(mt.paramTypes, rt) if (mt.paramTypes.nonEmpty || ft <:< pt) ft else rt - } } + } case et: ExprType => et.resultType case _ => tp } diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index b2e9d639d..ba14b7498 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -1314,6 +1314,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit val self1 = typed(self)(ctx.outer).asInstanceOf[ValDef] // outer context where class members are not visible val dummy = localDummy(cls, impl) val body1 = typedStats(impl.body, dummy)(inClassContext(self1.symbol)) + cls.setNoInitsFlags((NoInitsInterface /: body1)((fs, stat) => fs & defKind(stat))) // Expand comments and type usecases cookComments(body1.map(_.symbol), self1.symbol)(localContext(cdef, cls).setNewScope) diff --git a/compiler/src/dotty/tools/dotc/util/CommentParsing.scala b/compiler/src/dotty/tools/dotc/util/CommentParsing.scala index cc790d683..59b3c61b1 100644 --- a/compiler/src/dotty/tools/dotc/util/CommentParsing.scala +++ b/compiler/src/dotty/tools/dotc/util/CommentParsing.scala @@ -13,7 +13,7 @@ package dotty.tools.dotc.util * handled by dottydoc. */ object CommentParsing { - import scala.reflect.internal.Chars._ + import Chars._ /** Returns index of string `str` following `start` skipping longest * sequence of whitespace characters characters (but no newlines) diff --git a/compiler/src/dotty/tools/dotc/util/FreshNameCreator.scala b/compiler/src/dotty/tools/dotc/util/FreshNameCreator.scala index 521947895..8892a570e 100644 --- a/compiler/src/dotty/tools/dotc/util/FreshNameCreator.scala +++ b/compiler/src/dotty/tools/dotc/util/FreshNameCreator.scala @@ -6,11 +6,6 @@ import scala.collection.mutable trait FreshNameCreator { def newName(prefix: String = ""): String - - @deprecated("use newName(prefix)", "2.9.0") - def newName(pos: scala.reflect.internal.util.Position, prefix: String): String = newName(prefix) - @deprecated("use newName()", "2.9.0") - def newName(pos: scala.reflect.internal.util.Position): String = newName() } object FreshNameCreator { diff --git a/compiler/src/dotty/tools/dotc/util/ShowPickled.scala b/compiler/src/dotty/tools/dotc/util/ShowPickled.scala index 477449074..3e06b3f91 100644 --- a/compiler/src/dotty/tools/dotc/util/ShowPickled.scala +++ b/compiler/src/dotty/tools/dotc/util/ShowPickled.scala @@ -5,13 +5,11 @@ import java.io.{File, FileInputStream, PrintStream} import java.lang.Long.toHexString import java.lang.Float.intBitsToFloat import java.lang.Double.longBitsToDouble -import scala.reflect.internal.Flags -import scala.reflect.internal.pickling.PickleFormat import core.unpickleScala2.PickleBuffer import core.Names._ object ShowPickled { - import PickleFormat._ + import core.unpickleScala2.PickleFormat._ case class PickleBufferEntry(num: Int, startIndex: Int, tag: Int, bytes: Array[Byte]) { def isName = tag == TERMname || tag == TYPEname diff --git a/compiler/src/dotty/tools/io/ClassPath.scala b/compiler/src/dotty/tools/io/ClassPath.scala index e30eca492..3afbed838 100644 --- a/compiler/src/dotty/tools/io/ClassPath.scala +++ b/compiler/src/dotty/tools/io/ClassPath.scala @@ -8,7 +8,7 @@ package io import java.net.URL import scala.collection.{ mutable, immutable } -import scala.reflect.internal.util.StringOps.splitWhere +import dotc.core.Decorators.StringDecorator import File.pathSeparator import java.net.MalformedURLException import Jar.isJarOrZip @@ -238,7 +238,7 @@ abstract class ClassPath { * Does not support nested classes on .NET */ def findClass(name: String): Option[AnyClassRep] = - splitWhere(name, _ == '.', true) match { + name.splitWhere(_ == '.', doDropIndex = true) match { case Some((pkg, rest)) => val rep = packages find (_.name == pkg) flatMap (_ findClass rest) rep map { diff --git a/compiler/src/dotty/tools/package.scala b/compiler/src/dotty/tools/package.scala index 5dae82b71..68d24e229 100644 --- a/compiler/src/dotty/tools/package.scala +++ b/compiler/src/dotty/tools/package.scala @@ -2,9 +2,6 @@ package dotty import scala.annotation.Annotation package object tools { - type FatalError = scala.reflect.internal.FatalError - val FatalError = scala.reflect.internal.FatalError - class sharable extends Annotation class unshared extends Annotation |