diff options
97 files changed, 963 insertions, 440 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/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala index 27be8c9d6..669e5429c 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -712,8 +712,11 @@ object Trees { override def toList: List[Tree[T]] = flatten(trees) override def toString = if (isEmpty) "EmptyTree" else "Thicket(" + trees.mkString(", ") + ")" override def withPos(pos: Position): this.type = { - val newTrees = trees.map(_.withPos(pos)) - new Thicket[T](newTrees).asInstanceOf[this.type] + val newTrees = trees.mapConserve(_.withPos(pos)) + if (trees eq newTrees) + this + else + new Thicket[T](newTrees).asInstanceOf[this.type] } override def pos = (NoPosition /: trees) ((pos, t) => pos union t.pos) override def foreachInThicket(op: Tree[T] => Unit): Unit = 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/ScalaSettings.scala b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala index fd79fcaa6..40e2b083b 100644 --- a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala +++ b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala @@ -1,6 +1,8 @@ package dotty.tools.dotc package config +import java.io.File + import PathResolver.Defaults import rewrite.Rewrites @@ -111,7 +113,7 @@ class ScalaSettings extends Settings.SettingGroup { "-project", "project title", "The name of the project", - sys.props("user.dir").split(sys.props("file.separator")).last + sys.props("user.dir").split(File.separatorChar).last ) val wikiSyntax = BooleanSetting("-Xwiki-syntax", "Retains the Scala2 behavior of using Wiki Syntax in Scaladoc") 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/ConstraintHandling.scala b/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala index 89861f6db..2a1f4ee6e 100644 --- a/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala +++ b/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala @@ -275,9 +275,6 @@ trait ConstraintHandling { if (fromBelow && isOrType(inst) && isFullyDefined(inst) && !isOrType(upperBound)) inst = ctx.harmonizeUnion(inst) - // 3. If instance is from below, and upper bound has open named parameters - // make sure the instance has all named parameters of the bound. - if (fromBelow) inst = inst.widenToNamedTypeParams(param.namedTypeParams) inst } 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 5a2e26099..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 diff --git a/compiler/src/dotty/tools/dotc/core/Flags.scala b/compiler/src/dotty/tools/dotc/core/Flags.scala index 63fbc98dc..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. */ @@ -613,9 +616,6 @@ object Flags { /** A private parameter accessor */ final val PrivateParamAccessor = allOf(Private, ParamAccessor) - /** A type parameter introduced with [type ... ] */ - final val NamedTypeParam = allOf(TypeParam, ParamAccessor) - /** A local parameter */ final val ParamAndLocal = allOf(Param, Local) 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/StdNames.scala b/compiler/src/dotty/tools/dotc/core/StdNames.scala index 0f1b296b1..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 diff --git a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala index a3475e14c..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) } @@ -1086,9 +1086,6 @@ object SymDenotations { /** The type parameters of a class symbol, Nil for all other symbols */ def typeParams(implicit ctx: Context): List[TypeSymbol] = Nil - /** The named type parameters declared or inherited by this symbol */ - def namedTypeParams(implicit ctx: Context): Set[TypeSymbol] = Set() - /** The type This(cls), where cls is this class, NoPrefix for all other symbols */ def thisType(implicit ctx: Context): Type = NoPrefix @@ -1226,11 +1223,9 @@ object SymDenotations { /** TODO: Document why caches are supposedly safe to use */ private[this] var myTypeParams: List[TypeSymbol] = _ - private[this] var myNamedTypeParams: Set[TypeSymbol] = _ - /** The type parameters in this class, in the order they appear in the current * scope `decls`. This might be temporarily the incorrect order when - * reading Scala2 pickled info. The problem is fixed by `updateTypeParams` + * reading Scala2 pickled info. The problem is fixed by `ensureTypeParamsInCorrectOrder`, * which is called once an unpickled symbol has been completed. */ private def typeParamsFromDecls(implicit ctx: Context) = @@ -1253,16 +1248,6 @@ object SymDenotations { myTypeParams } - /** The named type parameters declared or inherited by this class */ - override final def namedTypeParams(implicit ctx: Context): Set[TypeSymbol] = { - def computeNamedTypeParams: Set[TypeSymbol] = - if (ctx.erasedTypes || is(Module)) Set() // fast return for modules to avoid scanning package decls - else memberNames(abstractTypeNameFilter).map(name => - info.member(name).symbol.asType).filter(_.is(TypeParam, butNot = ExpandedName)).toSet - if (myNamedTypeParams == null) myNamedTypeParams = computeNamedTypeParams - myNamedTypeParams - } - override protected[dotc] final def info_=(tp: Type) = { super.info_=(tp) myTypeParams = null // changing the info might change decls, and with it typeParams 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/TypeApplications.scala b/compiler/src/dotty/tools/dotc/core/TypeApplications.scala index 70819e590..c713cd542 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeApplications.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeApplications.scala @@ -246,67 +246,6 @@ class TypeApplications(val self: Type) extends AnyVal { case _ => Nil } - /** The named type parameters declared or inherited by this type. - * These are all uninstantiated named type parameters of this type or one - * of its base types. - */ - final def namedTypeParams(implicit ctx: Context): Set[TypeSymbol] = self match { - case self: ClassInfo => - self.cls.namedTypeParams - case self: RefinedType => - self.parent.namedTypeParams.filterNot(_.name == self.refinedName) - case self: SingletonType => - Set() - case self: TypeProxy => - self.underlying.namedTypeParams - case _ => - Set() - } - - /** The smallest supertype of this type that instantiated none of the named type parameters - * in `params`. That is, for each named type parameter `p` in `params`, either there is - * no type field named `p` in this type, or `p` is a named type parameter of this type. - * The first case is important for the recursive case of AndTypes, because some of their operands might - * be missing the named parameter altogether, but the AndType as a whole can still - * contain it. - */ - final def widenToNamedTypeParams(params: Set[TypeSymbol])(implicit ctx: Context): Type = { - - /** Is widening not needed for `tp`? */ - def isOK(tp: Type) = { - val ownParams = tp.namedTypeParams - def isMissingOrOpen(param: TypeSymbol) = { - val ownParam = tp.nonPrivateMember(param.name).symbol - !ownParam.exists || ownParams.contains(ownParam.asType) - } - params.forall(isMissingOrOpen) - } - - /** Widen type by forming the intersection of its widened parents */ - def widenToParents(tp: Type) = { - val parents = tp.parents.map(p => - tp.baseTypeWithArgs(p.symbol).widenToNamedTypeParams(params)) - parents.reduceLeft(ctx.typeComparer.andType(_, _)) - } - - if (isOK(self)) self - else self match { - case self @ AppliedType(tycon, args) if !isOK(tycon) => - widenToParents(self) - case self: TypeRef if self.symbol.isClass => - widenToParents(self) - case self: RefinedType => - val parent1 = self.parent.widenToNamedTypeParams(params) - if (params.exists(_.name == self.refinedName)) parent1 - else self.derivedRefinedType(parent1, self.refinedName, self.refinedInfo) - case self: TypeProxy => - self.superType.widenToNamedTypeParams(params) - case self: AndOrType => - self.derivedAndOrType( - self.tp1.widenToNamedTypeParams(params), self.tp2.widenToNamedTypeParams(params)) - } - } - /** Is self type higher-kinded (i.e. of kind != "*")? */ def isHK(implicit ctx: Context): Boolean = self.dealias match { case self: TypeRef => self.info.isHK diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala index e423dd686..b61fccf31 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala @@ -1264,22 +1264,10 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { } } - /** `op(tp1, tp2)` unless `tp1` and `tp2` are type-constructors with at least - * some unnamed type parameters. + /** `op(tp1, tp2)` unless `tp1` and `tp2` are type-constructors. * In the latter case, combine `tp1` and `tp2` under a type lambda like this: * * [X1, ..., Xn] -> op(tp1[X1, ..., Xn], tp2[X1, ..., Xn]) - * - * Note: There is a tension between named and positional parameters here, which - * is impossible to resolve completely. Say you have - * - * C[type T], D[type U] - * - * Then do you expand `C & D` to `[T] -> C[T] & D[T]` or not? Under the named - * type parameter interpretation, this would be wrong whereas under the traditional - * higher-kinded interpretation this would be required. The problem arises from - * allowing both interpretations. A possible remedy is to be somehow stricter - * in where we allow which interpretation. */ private def liftIfHK(tp1: Type, tp2: Type, op: (Type, Type) => Type, original: (Type, Type) => Type) = { val tparams1 = tp1.typeParams diff --git a/compiler/src/dotty/tools/dotc/core/TypeOps.scala b/compiler/src/dotty/tools/dotc/core/TypeOps.scala index 308e6e306..6c40794e3 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeOps.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeOps.scala @@ -428,16 +428,10 @@ trait TypeOps { this: Context => // TODO: Make standalone object. case tp: TypeRef => tp case tp @ RefinedType(tp1, name: TypeName, rinfo) => - rinfo match { - case TypeAlias(TypeRef(pre, name1)) if name1 == name && (pre =:= cls.thisType) => - // Don't record refinements of the form X = this.X (These can arise using named parameters). - typr.println(s"dropping refinement $tp") - case _ => - val prevInfo = refinements(name) - refinements = refinements.updated(name, - if (prevInfo == null) tp.refinedInfo else prevInfo & tp.refinedInfo) - formals = formals.updated(name, tp1.typeParamNamed(name)) - } + val prevInfo = refinements(name) + refinements = refinements.updated(name, + if (prevInfo == null) tp.refinedInfo else prevInfo & tp.refinedInfo) + formals = formals.updated(name, tp1.typeParamNamed(name)) normalizeToRef(tp1) case _: ErrorType => defn.AnyType diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 36e0dfb0e..546473b68 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._ @@ -549,13 +550,7 @@ object Types { def goThis(tp: ThisType) = { val d = go(tp.underlying) - if (d.exists) - if ((pre eq tp) && d.symbol.is(NamedTypeParam) && (d.symbol.owner eq tp.cls)) - // If we look for a named type parameter `P` in `C.this.P`, looking up - // the fully applied self type of `C` will give as an info the alias type - // `P = this.P`. We need to return a denotation with the underlying bounds instead. - d.symbol.denot - else d + if (d.exists) d else // There is a special case to handle: // trait Super { this: Sub => private class Inner {} println(this.Inner) } @@ -2069,6 +2064,9 @@ object Types { */ abstract case class RefinedType(parent: Type, refinedName: Name, refinedInfo: Type) extends RefinedOrRecType { + if (refinedName.isTermName) assert(refinedInfo.isInstanceOf[TermType]) + else assert(refinedInfo.isInstanceOf[TypeType]) + override def underlying(implicit ctx: Context) = parent private def badInst = @@ -3859,7 +3857,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/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index c14108d2e..65c7a290d 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -805,7 +805,7 @@ object Parsers { private def simpleTypeRest(t: Tree): Tree = in.token match { case HASH => simpleTypeRest(typeProjection(t)) case LBRACKET => simpleTypeRest(atPos(startOffset(t)) { - AppliedTypeTree(t, typeArgs(namedOK = true, wildOK = true)) }) + AppliedTypeTree(t, typeArgs(namedOK = false, wildOK = true)) }) case _ => t } @@ -1607,6 +1607,7 @@ object Parsers { * LocalModifier ::= abstract | final | sealed | implicit | lazy */ def modifiers(allowed: BitSet = modifierTokens, start: Modifiers = Modifiers()): Modifiers = { + @tailrec def loop(mods: Modifiers): Modifiers = { if (allowed contains in.token) { val isAccessMod = accessModifierTokens contains in.token @@ -1663,7 +1664,7 @@ object Parsers { /* -------- PARAMETERS ------------------------------------------- */ /** ClsTypeParamClause::= `[' ClsTypeParam {`,' ClsTypeParam} `]' - * ClsTypeParam ::= {Annotation} [{Modifier} type] [`+' | `-'] + * ClsTypeParam ::= {Annotation} [`+' | `-'] * id [HkTypeParamClause] TypeParamBounds * * DefTypeParamClause::= `[' DefTypeParam {`,' DefTypeParam} `]' @@ -1679,25 +1680,17 @@ object Parsers { def typeParam(): TypeDef = { val isConcreteOwner = ownerKind == ParamOwner.Class || ownerKind == ParamOwner.Def val start = in.offset - var mods = annotsAsMods() - if (ownerKind == ParamOwner.Class) { - mods = modifiers(start = mods) - mods = - atPos(start, in.offset) { - if (in.token == TYPE) { - val mod = atPos(in.skipToken()) { Mod.Type() } - (mods | Param | ParamAccessor).withAddedMod(mod) - } else { - if (mods.hasFlags) syntaxError(TypeParamsTypeExpected(mods, ident())) - mods | Param | PrivateLocal - } - } - } - else mods = atPos(start) (mods | Param) - if (ownerKind != ParamOwner.Def) { - if (isIdent(nme.raw.PLUS)) mods |= Covariant - else if (isIdent(nme.raw.MINUS)) mods |= Contravariant - if (mods is VarianceFlags) in.nextToken() + val mods = atPos(start) { + annotsAsMods() | { + if (ownerKind == ParamOwner.Class) Param | PrivateLocal + else Param + } | { + if (ownerKind != ParamOwner.Def) + if (isIdent(nme.raw.PLUS)) { in.nextToken(); Covariant } + else if (isIdent(nme.raw.MINUS)) { in.nextToken(); Contravariant } + else EmptyFlags + else EmptyFlags + } } atPos(start, nameStart) { val name = @@ -2057,7 +2050,7 @@ object Parsers { val name = ident().toTypeName val constr = atPos(in.lastOffset) { val tparams = typeParamClauseOpt(ParamOwner.Class) - val cmods = constrModsOpt() + val cmods = constrModsOpt(name) val vparamss = paramClauses(name, mods is Case) makeConstructor(tparams, vparamss).withMods(cmods) @@ -2070,11 +2063,11 @@ object Parsers { /** ConstrMods ::= AccessModifier * | Annotation {Annotation} (AccessModifier | `this') */ - def constrModsOpt(): Modifiers = { + def constrModsOpt(owner: Name): Modifiers = { val mods = modifiers(accessModifierTokens, annotsAsMods()) if (mods.hasAnnotations && !mods.hasFlags) if (in.token == THIS) in.nextToken() - else syntaxError("`private', `protected', or `this' expected") + else syntaxError(AnnotatedPrimaryConstructorRequiresModifierOrThis(owner), mods.annotations.last.pos) mods } 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/SyntaxHighlighting.scala b/compiler/src/dotty/tools/dotc/printing/SyntaxHighlighting.scala index 86f34e64d..e20f846ac 100644 --- a/compiler/src/dotty/tools/dotc/printing/SyntaxHighlighting.scala +++ b/compiler/src/dotty/tools/dotc/printing/SyntaxHighlighting.scala @@ -6,6 +6,7 @@ import parsing.Tokens._ import scala.annotation.switch import scala.collection.mutable.StringBuilder import core.Contexts.Context +import util.Chars.{ LF, FF, CR, SU } import Highlighting.{Highlight, HighlightBuffer} /** This object provides functions for syntax highlighting in the REPL */ @@ -26,7 +27,7 @@ object SyntaxHighlighting { private def valDef(str: String) = ValDefColor + str + NoColor private def operator(str: String) = TypeColor + str + NoColor private def annotation(str: String) = - if (str.trim == "@") str else AnnotationColor + str + NoColor + if (str.trim == "@") str else { AnnotationColor + str + NoColor } private val tripleQs = Console.RED_B + "???" + NoColor private val keywords: Seq[String] = for { @@ -152,7 +153,11 @@ object SyntaxHighlighting { var open = 1 while (open > 0 && remaining.nonEmpty) { curr = takeChar() - newBuf += curr + if (curr == '@') { + appendWhile('@', !typeEnders.contains(_), annotation) + newBuf append CommentColor + } + else newBuf += curr if (curr == '*' && remaining.nonEmpty) { curr = takeChar() @@ -163,6 +168,11 @@ object SyntaxHighlighting { newBuf += curr if (curr == '*') open += 1 } + + (curr: @switch) match { + case LF | FF | CR | SU => newBuf append CommentColor + case _ => () + } } prev = curr newBuf append NoColor @@ -236,6 +246,11 @@ object SyntaxHighlighting { newBuf += curr closing = 0 } + + (curr: @switch) match { + case LF | FF | CR | SU => newBuf append LiteralColor + case _ => () + } } newBuf append NoColor prev = curr diff --git a/compiler/src/dotty/tools/dotc/reporting/MessageRendering.scala b/compiler/src/dotty/tools/dotc/reporting/MessageRendering.scala index 190445d60..17eb8d39b 100644 --- a/compiler/src/dotty/tools/dotc/reporting/MessageRendering.scala +++ b/compiler/src/dotty/tools/dotc/reporting/MessageRendering.scala @@ -5,9 +5,12 @@ package reporting import core.Contexts.Context import core.Decorators._ import printing.Highlighting.{Blue, Red} +import printing.SyntaxHighlighting import diagnostic.{ErrorMessageID, Message, MessageContainer, NoExplanation} import diagnostic.messages._ import util.SourcePosition +import util.Chars.{ LF, CR, FF, SU } +import scala.annotation.switch import scala.collection.mutable @@ -38,20 +41,37 @@ trait MessageRendering { */ def sourceLines(pos: SourcePosition)(implicit ctx: Context): (List[String], List[String], Int) = { var maxLen = Int.MinValue - def render(xs: List[Int]) = - xs.map(pos.source.offsetToLine(_)) - .map { lineNbr => - val prefix = s"${lineNbr + 1} |" - maxLen = math.max(maxLen, prefix.length) - (prefix, pos.lineContent(lineNbr).stripLineEnd) - } - .map { case (prefix, line) => - val lnum = Red(" " * math.max(0, maxLen - prefix.length) + prefix) - hl"$lnum$line" - } + def render(offsetAndLine: (Int, String)): String = { + val (offset, line) = offsetAndLine + val lineNbr = pos.source.offsetToLine(offset) + val prefix = s"${lineNbr + 1} |" + maxLen = math.max(maxLen, prefix.length) + val lnum = Red(" " * math.max(0, maxLen - prefix.length) + prefix).show + lnum + line.stripLineEnd + } + + def linesFrom(arr: Array[Char]): List[String] = { + def pred(c: Char) = (c: @switch) match { + case LF | CR | FF | SU => true + case _ => false + } + val (line, rest0) = arr.span(!pred(_)) + val (_, rest) = rest0.span(pred) + new String(line) :: { if (rest.isEmpty) Nil else linesFrom(rest) } + } + val syntax = + if (ctx.settings.color.value != "never") + SyntaxHighlighting(pos.linesSlice).toArray + else pos.linesSlice + val lines = linesFrom(syntax) val (before, after) = pos.beforeAndAfterPoint - (render(before), render(after), maxLen) + + ( + before.zip(lines).map(render), + after.zip(lines.drop(before.length)).map(render), + maxLen + ) } /** The column markers aligned under the error */ diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java b/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java index 2bf15cb7c..7b56c8ed4 100644 --- a/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java +++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java @@ -32,7 +32,6 @@ public enum ErrorMessageID { ByNameParameterNotSupportedID, WrongNumberOfTypeArgsID, IllegalVariableInPatternAlternativeID, - TypeParamsTypeExpectedID, IdentifierExpectedID, AuxConstructorNeedsNonImplicitParameterID, IncorrectRepeatedParameterSyntaxID, @@ -51,6 +50,11 @@ public enum ErrorMessageID { ExpectedTokenButFoundID, 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 4599665c8..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 { @@ -691,19 +692,6 @@ object messages { } } - case class TypeParamsTypeExpected(mods: untpd.Modifiers, identifier: TermName)(implicit ctx: Context) - extends Message(TypeParamsTypeExpectedID) { - val kind = "Syntax" - val msg = hl"""Expected ${"type"} keyword for type parameter $identifier""" - val explanation = - hl"""|This happens when you add modifiers like ${"private"} or ${"protected"} - |to your type parameter definition without adding the ${"type"} keyword. - | - |Add ${"type"} to your code, e.g.: - |${s"trait A[${mods.flags} type $identifier]"} - |""" - } - case class IdentifierExpected(identifier: String)(implicit ctx: Context) extends Message(IdentifierExpectedID) { val kind = "Syntax" @@ -1146,4 +1134,62 @@ object messages { |""".stripMargin } + case class AnnotatedPrimaryConstructorRequiresModifierOrThis(cls: Name)(implicit ctx: Context) + extends Message(AnnotatedPrimaryConstructorRequiresModifierOrThisID) { + val kind = "Syntax" + val msg = hl"""${"private"}, ${"protected"}, or ${"this"} expected for annotated primary constructor""" + val explanation = + hl"""|When using annotations with a primary constructor of a class, + |the annotation must be followed by an access modifier + |(${"private"} or ${"protected"}) or ${"this"}. + | + |For example: + | ${"class Sample @deprecated this(param: Parameter) { ..."} + | ^^^^ + |""".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/sbt/ExtractAPI.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala index 7f44af486..599522b74 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala @@ -350,7 +350,7 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder case tp: NamedType => val sym = tp.symbol // Normalize package prefix to avoid instability of representation - val prefix = if (sym.isClass && sym.owner.is(Package)) + val prefix = if (sym.owner.is(Package)) sym.owner.thisType else tp.prefix @@ -358,7 +358,7 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder case TypeApplications.AppliedType(tycon, args) => def processArg(arg: Type): api.Type = arg match { case arg @ TypeBounds(lo, hi) => // Handle wildcard parameters - if (lo.eq(defn.NothingType) && hi.eq(defn.AnyType)) + if (lo.isDirectRef(defn.NothingClass) && hi.isDirectRef(defn.AnyClass)) Constants.emptyType else { val name = "_" 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 e45924f83..a65ef00cc 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -1381,7 +1381,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic => else WildcardType) val commonFormal = defn.FunctionOf(commonParamTypes, WildcardType) overload.println(i"pretype arg $arg with expected type $commonFormal") - pt.typedArg(arg, commonFormal) + pt.typedArg(arg, commonFormal)(ctx.addMode(Mode.ImplicitsEnabled)) } } } diff --git a/compiler/src/dotty/tools/dotc/typer/Checking.scala b/compiler/src/dotty/tools/dotc/typer/Checking.scala index 48f9243f7..1ca7eb107 100644 --- a/compiler/src/dotty/tools/dotc/typer/Checking.scala +++ b/compiler/src/dotty/tools/dotc/typer/Checking.scala @@ -327,7 +327,7 @@ object Checking { if (!sym.is(Deferred)) fail(i"`@native' members may not have implementation") } - else if (sym.is(Deferred, butNot = Param) && !sym.isSelfSym) { + else if (sym.is(Deferred, butNot = Param) && !sym.isType && !sym.isSelfSym) { if (!sym.owner.isClass || sym.owner.is(Module) || sym.owner.isAnonymousClass) fail(i"only classes can have declared but undefined members$varNote") checkWithDeferred(Private) 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 d5afae90c..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 { @@ -496,6 +514,7 @@ trait Implicits { self: Typer => || (to isRef defn.UnitClass) || (from.tpe isRef defn.NothingClass) || (from.tpe isRef defn.NullClass) + || !(ctx.mode is Mode.ImplicitsEnabled) || (from.tpe eq NoPrefix)) NoImplicitMatches else try inferImplicit(to.stripTypeVar.widenExpr, from, from.pos) diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala index d5f171fe3..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 => @@ -753,11 +819,10 @@ class Namer { typer: Typer => /* Check parent type tree `parent` for the following well-formedness conditions: * (1) It must be a class type with a stable prefix (@see checkClassTypeWithStablePrefix) * (2) If may not derive from itself - * (3) Overriding type parameters must be correctly forwarded. (@see checkTypeParamOverride) - * (4) The class is not final - * (5) If the class is sealed, it is defined in the same compilation unit as the current class + * (3) The class is not final + * (4) If the class is sealed, it is defined in the same compilation unit as the current class */ - def checkedParentType(parent: untpd.Tree, paramAccessors: List[Symbol]): Type = { + def checkedParentType(parent: untpd.Tree): Type = { val ptype = parentType(parent)(ctx.superCallContext) if (cls.isRefinementClass) ptype else { @@ -772,8 +837,6 @@ class Namer { typer: Typer => ctx.error(i"cyclic inheritance: $cls extends itself$addendum", parent.pos) defn.ObjectType } - else if (!paramAccessors.forall(checkTypeParamOverride(pt, _))) - defn.ObjectType else { val pclazz = pt.typeSymbol if (pclazz.is(Final)) @@ -785,47 +848,7 @@ class Namer { typer: Typer => } } - /* Check that every parameter with the same name as a visible named parameter in the parent - * class satisfies the following two conditions: - * (1) The overriding parameter is also named (i.e. not local/name mangled). - * (2) The overriding parameter is passed on directly to the parent parameter, or the - * parent parameter is not fully defined. - * @return true if conditions are satisfied, false otherwise. - */ - def checkTypeParamOverride(parent: Type, paramAccessor: Symbol): Boolean = { - var ok = true - val pname = paramAccessor.name - - def illegal(how: String): Unit = { - ctx.error(em"Illegal override of public type parameter $pname in $parent$how", paramAccessor.pos) - ok = false - } - - def checkAlias(tp: Type): Unit = tp match { - case tp: RefinedType => - if (tp.refinedName == pname) - tp.refinedInfo match { - case TypeAlias(alias) => - alias match { - case TypeRef(pre, name1) if name1 == pname && (pre =:= cls.thisType) => - // OK, parameter is passed on directly - case _ => - illegal(em".\nParameter is both redeclared and instantiated with $alias.") - } - case _ => // OK, argument is not fully defined - } - else checkAlias(tp.parent) - case _ => - } - if (parent.nonPrivateMember(paramAccessor.name).symbol.is(Param)) - if (paramAccessor is Private) - illegal("\nwith private parameter. Parameter definition needs to be prefixed with `type'.") - else - checkAlias(parent) - ok - } - - addAnnotations(denot.symbol, original) + addAnnotations(denot.symbol, original) val selfInfo = if (self.isEmpty) NoType @@ -853,8 +876,7 @@ class Namer { typer: Typer => indexAndAnnotate(rest)(inClassContext(selfInfo)) - val tparamAccessors = decls.filter(_ is TypeParamAccessor).toList - val parentTypes = ensureFirstIsClass(parents.map(checkedParentType(_, tparamAccessors))) + val parentTypes = ensureFirstIsClass(parents.map(checkedParentType(_))) val parentRefs = ctx.normalizeToClassRefs(parentTypes, cls, decls) typr.println(s"completing $denot, parents = $parents, parentTypes = $parentTypes, parentRefs = $parentRefs") @@ -862,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/RefChecks.scala b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala index 7c573d23c..23d05e087 100644 --- a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala +++ b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala @@ -241,8 +241,6 @@ object RefChecks { isDefaultGetter(member.name) || // default getters are not checked for compatibility memberTp.overrides(otherTp) - def domain(sym: Symbol): Set[Name] = sym.info.namedTypeParams.map(_.name) - //Console.println(infoString(member) + " overrides " + infoString(other) + " in " + clazz);//DEBUG // return if we already checked this combination elsewhere @@ -344,9 +342,6 @@ object RefChecks { overrideError("cannot be used here - only term macros can override term macros") } else if (!compatibleTypes) { overrideError("has incompatible type" + err.whyNoMatchStr(memberTp, otherTp)) - } else if (member.isType && domain(member) != domain(other)) { - overrideError("has different named type parameters: "+ - i"[${domain(member).toList}%, %] instead of [${domain(other).toList}%, %]") } else { checkOverrideDeprecated() } diff --git a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala index 53ce5555b..6bf8dcbbc 100644 --- a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala +++ b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala @@ -199,10 +199,7 @@ trait TypeAssigner { } } else if (d.symbol is TypeParamAccessor) - if (d.info.isAlias) - ensureAccessible(d.info.bounds.hi, superAccess, pos) - else // It's a named parameter, use the non-symbolic representation to pick up inherited versions as well - d.symbol.owner.thisType.select(d.symbol.name) + ensureAccessible(d.info.bounds.hi, superAccess, pos) else ctx.makePackageObjPrefixExplicit(tpe withDenot d) case _ => @@ -452,23 +449,10 @@ trait TypeAssigner { } def assignType(tree: untpd.AppliedTypeTree, tycon: Tree, args: List[Tree])(implicit ctx: Context) = { + assert(!hasNamedArg(args)) val tparams = tycon.tpe.typeParams - lazy val ntparams = tycon.tpe.namedTypeParams - def refineNamed(tycon: Type, arg: Tree) = arg match { - case ast.Trees.NamedArg(name, argtpt) => - // Dotty deviation: importing ast.Trees._ and matching on NamedArg gives a cyclic ref error - val tparam = tparams.find(_.paramName == name) match { - case Some(tparam) => tparam - case none => ntparams.find(_.name == name).getOrElse(NoSymbol) - } - if (tparam.isTypeParam) RefinedType(tycon, name, argtpt.tpe.toBounds(tparam)) - else errorType(i"$tycon does not have a parameter or abstract type member named $name", arg.pos) - case _ => - errorType(s"named and positional type arguments may not be mixed", arg.pos) - } val ownType = - if (hasNamedArg(args)) (tycon.tpe /: args)(refineNamed) - else if (sameLength(tparams, args)) tycon.tpe.appliedTo(args.tpes) + if (sameLength(tparams, args)) tycon.tpe.appliedTo(args.tpes) else wrongNumberOfTypeArgs(tycon.tpe, tparams, args, tree.pos) tree.withType(ownType) } diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 33e320ce5..ba14b7498 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -1064,23 +1064,21 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit } else { var args = tree.args - val args1 = - if (hasNamedArg(args)) typedNamedArgs(args) - else { - if (args.length != tparams.length) { - wrongNumberOfTypeArgs(tpt1.tpe, tparams, args, tree.pos) - args = args.take(tparams.length) - } - def typedArg(arg: untpd.Tree, tparam: TypeParamInfo) = { - val (desugaredArg, argPt) = - if (ctx.mode is Mode.Pattern) - (if (isVarPattern(arg)) desugar.patternVar(arg) else arg, tparam.paramBounds) - else - (arg, WildcardType) - typed(desugaredArg, argPt) - } - args.zipWithConserve(tparams)(typedArg(_, _)).asInstanceOf[List[Tree]] + val args1 = { + if (args.length != tparams.length) { + wrongNumberOfTypeArgs(tpt1.tpe, tparams, args, tree.pos) + args = args.take(tparams.length) + } + def typedArg(arg: untpd.Tree, tparam: TypeParamInfo) = { + val (desugaredArg, argPt) = + if (ctx.mode is Mode.Pattern) + (if (isVarPattern(arg)) desugar.patternVar(arg) else arg, tparam.paramBounds) + else + (arg, WildcardType) + typed(desugaredArg, argPt) } + args.zipWithConserve(tparams)(typedArg(_, _)).asInstanceOf[List[Tree]] + } // check that arguments conform to bounds is done in phase PostTyper assignType(cpy.AppliedTypeTree(tree)(tpt1, args1), tpt1, args1) } @@ -1316,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) @@ -2023,7 +2022,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit // try an implicit conversion inferView(tree, pt) match { case SearchSuccess(inferred, _, _, _) => - adapt(inferred, pt) + adapt(inferred, pt)(ctx.retractMode(Mode.ImplicitsEnabled)) case failure: SearchFailure => if (pt.isInstanceOf[ProtoType] && !failure.isInstanceOf[AmbiguousImplicits]) tree else err.typeMismatch(tree, pt, failure) 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/dotc/util/SourcePosition.scala b/compiler/src/dotty/tools/dotc/util/SourcePosition.scala index aad4995d8..be5c46995 100644 --- a/compiler/src/dotty/tools/dotc/util/SourcePosition.scala +++ b/compiler/src/dotty/tools/dotc/util/SourcePosition.scala @@ -12,9 +12,14 @@ extends interfaces.SourcePosition { def lineContent: String = source.lineContent(point) def point: Int = pos.point + /** The line of the position, starting at 0 */ def line: Int = source.offsetToLine(point) + /** Extracts the lines from the underlying source file as `Array[Char]`*/ + def linesSlice: Array[Char] = + source.content.slice(source.startOfLine(start), source.nextLine(end)) + /** The lines of the position */ def lines: List[Int] = List.range(source.offsetToLine(start), source.offsetToLine(end + 1)) match { @@ -25,9 +30,6 @@ extends interfaces.SourcePosition { def lineOffsets: List[Int] = lines.map(source.lineToOffset(_)) - def lineContent(lineNumber: Int): String = - source.lineContent(source.lineToOffset(lineNumber)) - def beforeAndAfterPoint: (List[Int], List[Int]) = lineOffsets.partition(_ <= point) 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 diff --git a/compiler/test/dotty/partest/DPConsoleRunner.scala b/compiler/test/dotty/partest/DPConsoleRunner.scala index 7a25af6b7..aa926efe2 100644 --- a/compiler/test/dotty/partest/DPConsoleRunner.scala +++ b/compiler/test/dotty/partest/DPConsoleRunner.scala @@ -4,6 +4,7 @@ package dotty.partest +import dotty.tools.FatalError import scala.reflect.io.AbstractFile import scala.tools.partest._ import scala.tools.partest.nest._ @@ -294,8 +295,6 @@ class DPTestRunner(testFile: File, suiteRunner: DPSuiteRunner) extends nest.Runn // override to add the check for nr of compilation errors if there's a // target.nerr file override def runNegTest() = runInContext { - import scala.reflect.internal.FatalError - sealed abstract class NegTestState // Don't get confused, the neg test passes when compilation fails for at // least one round (optionally checking the number of compiler errors and diff --git a/compiler/test/dotty/tools/dotc/parsing/ModifiersParsingTest.scala b/compiler/test/dotty/tools/dotc/parsing/ModifiersParsingTest.scala index 806e1af46..5144d81e4 100644 --- a/compiler/test/dotty/tools/dotc/parsing/ModifiersParsingTest.scala +++ b/compiler/test/dotty/tools/dotc/parsing/ModifiersParsingTest.scala @@ -95,9 +95,6 @@ class ModifiersParsingTest { source = "class A[T]" assert(source.firstTypeParam.modifiers == List()) - - source = "class A[type T]" - assert(source.firstTypeParam.modifiers == List(Mod.Type())) } @Test def typeDef = { diff --git a/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala b/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala index 971a40a1b..f11c6dd96 100644 --- a/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala +++ b/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala @@ -6,7 +6,7 @@ import core.Contexts.Context import diagnostic.messages._ import dotty.tools.dotc.parsing.Tokens import org.junit.Assert._ -import org.junit.Test +import org.junit.{Ignore, Test} class ErrorMessagesTests extends ErrorMessagesTest { // In the case where there are no errors, we can do "expectNoErrors" in the @@ -198,4 +198,111 @@ class ErrorMessagesTests extends ErrorMessagesTest { assertTrue("expected trait", isTrait) } + @Test def constructorModifier = + checkMessagesAfter("frontend") { + """ + |class AnotherClass @deprecated () + """.stripMargin + } + .expect { (ictx, messages) => + implicit val ctx: Context = ictx + val defn = ictx.definitions + + assertMessageCount(1, messages) + val AnnotatedPrimaryConstructorRequiresModifierOrThis(cls) :: Nil = messages + assertEquals("AnotherClass", cls.show) + } + + @Test def overloadedMethodNeedsReturnType = + checkMessagesAfter("frontend") { + """ + |class Scope() { + | def foo(i: Int) = foo(i.toString) + | def foo(s: String) = s + |} + """.stripMargin + } + .expect { (ictx, messages) => + implicit val ctx: Context = ictx + val defn = ictx.definitions + + assertMessageCount(1, messages) + val OverloadedOrRecursiveMethodNeedsResultType(tree) :: Nil = messages + assertEquals("foo", tree.show) + } + + @Test def recursiveMethodNeedsReturnType = + checkMessagesAfter("frontend") { + """ + |class Scope() { + | def i = i + 5 + |} + """.stripMargin + } + .expect { (ictx, messages) => + implicit val ctx: Context = ictx + val defn = ictx.definitions + + assertMessageCount(1, messages) + val OverloadedOrRecursiveMethodNeedsResultType(tree) :: Nil = messages + assertEquals("i", tree.show) + } + + @Test def recursiveValueNeedsReturnType = + checkMessagesAfter("frontend") { + """ + |class Scope() { + | lazy val i = i + 5 + |} + """.stripMargin + } + .expect { (ictx, messages) => + implicit val ctx: Context = ictx + val defn = ictx.definitions + + assertMessageCount(1, messages) + val RecursiveValueNeedsResultType(tree) :: Nil = messages + assertEquals("i", tree.show) + } + + @Test def cyclicReferenceInvolving = + checkMessagesAfter("frontend") { + """ + |class A { + | val x: T = ??? + | type T <: x.type // error: cyclic reference involving value x + |} + """.stripMargin + } + .expect { (ictx, messages) => + implicit val ctx: Context = ictx + val defn = ictx.definitions + + assertMessageCount(1, messages) + val CyclicReferenceInvolving(denot) :: Nil = messages + assertEquals("value x", denot.show) + } + + @Test def cyclicReferenceInvolvingImplicit = + checkMessagesAfter("frontend") { + """ + |object implicitDefs { + | def foo(implicit x: String) = 1 + | def bar() = { + | implicit val x = foo + | x + | } + |} + """.stripMargin + } + .expect { (ictx, messages) => + implicit val ctx: Context = ictx + val defn = ictx.definitions + + assertMessageCount(1, messages) + val CyclicReferenceInvolvingImplicit(tree) :: Nil = messages + assertEquals("x", tree.name.show) + } + + } diff --git a/compiler/test/dotty/tools/dotc/reporting/TestReporter.scala b/compiler/test/dotty/tools/dotc/reporting/TestReporter.scala index 70d18d031..169908c4f 100644 --- a/compiler/test/dotty/tools/dotc/reporting/TestReporter.scala +++ b/compiler/test/dotty/tools/dotc/reporting/TestReporter.scala @@ -7,7 +7,6 @@ import util.SourcePosition import core.Contexts._ import Reporter._ import java.io.PrintWriter -import scala.reflect.internal.util._ import diagnostic.{ Message, MessageContainer, NoExplanation } import diagnostic.messages._ diff --git a/doc-tool/resources/_layouts/api-page.html b/doc-tool/resources/_layouts/api-page.html index 878ec8d8f..2d2f0265a 100644 --- a/doc-tool/resources/_layouts/api-page.html +++ b/doc-tool/resources/_layouts/api-page.html @@ -134,12 +134,25 @@ extraCSS: {% endfor %} {% endif %} - {% if member.kind == "type" and member.alias != null %} + {% if member.kind == "type" %} + {% for tparam in member.typeParams %} + {% if forloop.first %} + <span class="no-left">[</span> + {% endif %} + {% if forloop.last %} + <span class="no-left">{{ tparam }}</span> + <span class="no-left">]</span> + {% else %} + <span class="no-left">{{ tparam }}, </span> + {% endif %} + {% endfor %} + {% if member.alias != null %} <span class="type-alias"> <span class="equals"> = </span> {% renderRef member.alias %} </span> {% endif %} + {% endif %} {% if member.returnValue %} <span class="no-left">: {% renderRef member.returnValue %}</span> diff --git a/doc-tool/resources/css/dottydoc.css b/doc-tool/resources/css/dottydoc.css index 7e7c501bf..0b833830c 100644 --- a/doc-tool/resources/css/dottydoc.css +++ b/doc-tool/resources/css/dottydoc.css @@ -328,3 +328,9 @@ pre > code.hljs { padding: 10px; background: transparent; } + +blockquote { + padding: 0 1em; + color: #777; + border-left: 0.25em solid #ddd; +} diff --git a/doc-tool/src/dotty/tools/dottydoc/core/DocASTPhase.scala b/doc-tool/src/dotty/tools/dottydoc/core/DocASTPhase.scala index 7f44c5656..cfb66fa56 100644 --- a/doc-tool/src/dotty/tools/dottydoc/core/DocASTPhase.scala +++ b/doc-tool/src/dotty/tools/dottydoc/core/DocASTPhase.scala @@ -8,7 +8,7 @@ import dotc.CompilationUnit import dotc.config.Printers.dottydoc import dotc.core.Contexts.Context import dotc.core.Comments.ContextDocstrings -import dotc.core.Types.NoType +import dotc.core.Types.{PolyType, NoType} import dotc.core.Phases.Phase import dotc.core.Symbols.{ Symbol, NoSymbol } @@ -92,8 +92,16 @@ class DocASTPhase extends Phase { val sym = t.symbol if (sym.is(Flags.Synthetic | Flags.Param)) NonEntity - else - TypeAliasImpl(sym, annotations(sym), flags(t), t.name.show.split("\\$\\$").last, path(sym), alias(t.rhs.tpe)) + else { + val tparams = t.rhs.tpe match { + case tp: PolyType => tp.paramRefs.zip(tp.variances).map { case (tp, variance) => + val varianceSym = if (variance == 1) "+" else if (variance == -1) "-" else "" + varianceSym + tp.paramName.show + } + case _ => Nil + } + TypeAliasImpl(sym, annotations(sym), flags(t), t.name.show.split("\\$\\$").last, path(sym), alias(t.rhs.tpe), tparams) + } /** trait */ case t @ TypeDef(n, rhs) if t.symbol.is(Flags.Trait) => diff --git a/doc-tool/src/dotty/tools/dottydoc/core/transform.scala b/doc-tool/src/dotty/tools/dottydoc/core/transform.scala index e4b9ae6b6..5174c0922 100644 --- a/doc-tool/src/dotty/tools/dottydoc/core/transform.scala +++ b/doc-tool/src/dotty/tools/dottydoc/core/transform.scala @@ -92,6 +92,7 @@ object transform { t.name, t.path, t.alias, + t.typeParams, t.comment, t.parent ) diff --git a/doc-tool/src/dotty/tools/dottydoc/model/JavaConverters.scala b/doc-tool/src/dotty/tools/dottydoc/model/JavaConverters.scala index 239656141..4a9bfce0c 100644 --- a/doc-tool/src/dotty/tools/dottydoc/model/JavaConverters.scala +++ b/doc-tool/src/dotty/tools/dottydoc/model/JavaConverters.scala @@ -189,6 +189,7 @@ object JavaConverters { "name" -> ent.name, "path" -> ent.path.asJava, "alias" -> ent.alias.map(_.asJava).asJava, + "typeParams" -> ent.typeParams.asJava, "comment" -> ent.comment.map(_.asJava).asJava, "hasShortenedDocstring" -> ent.hasShortenedDocstring, "isPrivate" -> ent.isPrivate, diff --git a/doc-tool/src/dotty/tools/dottydoc/model/comment/CommentParser.scala b/doc-tool/src/dotty/tools/dottydoc/model/comment/CommentParser.scala index b7a33a7ef..5ff28f914 100644 --- a/doc-tool/src/dotty/tools/dottydoc/model/comment/CommentParser.scala +++ b/doc-tool/src/dotty/tools/dottydoc/model/comment/CommentParser.scala @@ -6,6 +6,7 @@ import dotty.tools.dottydoc.util.syntax._ import dotty.tools.dotc.util.Positions._ import dotty.tools.dotc.core.Symbols._ import dotty.tools.dotc.core.Contexts.Context +import dotty.tools.dotc.core.Decorators._ import scala.collection.mutable import dotty.tools.dotc.config.Printers.dottydoc import scala.util.matching.Regex @@ -196,7 +197,7 @@ trait CommentParser extends util.MemberLookup { ) for ((key, _) <- bodyTags) ctx.docbase.warn( - s"Tag '@${key.name}' is not recognised", + hl"Tag '${"@" + key.name}' is not recognised", // FIXME: here the position is stretched out over the entire comment, // with the point being at the very end. This ensures that the entire // comment will be visible in error reporting. A more fine-grained diff --git a/doc-tool/src/dotty/tools/dottydoc/model/entities.scala b/doc-tool/src/dotty/tools/dottydoc/model/entities.scala index d35077816..d0f1a82c7 100644 --- a/doc-tool/src/dotty/tools/dottydoc/model/entities.scala +++ b/doc-tool/src/dotty/tools/dottydoc/model/entities.scala @@ -108,7 +108,7 @@ trait Package extends Entity with Members with SuperTypes { val kind = "package" } -trait TypeAlias extends Entity with Modifiers { +trait TypeAlias extends Entity with Modifiers with TypeParams { val kind = "type" def alias: Option[Reference] def isAbstract: Boolean = !alias.isDefined diff --git a/doc-tool/src/dotty/tools/dottydoc/model/factories.scala b/doc-tool/src/dotty/tools/dottydoc/model/factories.scala index 568b532b7..3e766a990 100644 --- a/doc-tool/src/dotty/tools/dottydoc/model/factories.scala +++ b/doc-tool/src/dotty/tools/dottydoc/model/factories.scala @@ -4,7 +4,8 @@ package model import comment._ import references._ import dotty.tools.dotc -import dotc.core.Types._ +import dotc.core.Types +import Types._ import dotc.core.TypeApplications._ import dotc.core.Contexts.Context import dotc.core.Symbols.{ Symbol, ClassSymbol } @@ -105,17 +106,8 @@ object factories { case ci: ClassInfo => typeRef(ci.cls.name.show, query = ci.typeSymbol.showFullName) - case tl: PolyType => { - // FIXME: should be handled correctly - // example, in `Option`: - // - // ```scala - // def companion: GenericCompanion[collection.Iterable] - // ``` - // - // Becomes: def companion: [+X0] -> collection.Iterable[X0] - typeRef(tl.show + " (not handled)") - } + case tl: PolyType => + expandTpe(tl.resType) case OrType(left, right) => OrTypeReference(expandTpe(left), expandTpe(right)) @@ -148,6 +140,8 @@ object factories { prefix + tp.name.show.split("\\$").last } .toList + case tp: Types.TypeAlias => + typeParams(tp.alias.typeSymbol) case _ => Nil } diff --git a/doc-tool/src/dotty/tools/dottydoc/model/internal.scala b/doc-tool/src/dotty/tools/dottydoc/model/internal.scala index bf50c0232..b50c93ee5 100644 --- a/doc-tool/src/dotty/tools/dottydoc/model/internal.scala +++ b/doc-tool/src/dotty/tools/dottydoc/model/internal.scala @@ -31,6 +31,7 @@ object internal { name: String, path: List[String], alias: Option[Reference], + typeParams: List[String] = Nil, var comment: Option[Comment] = None, var parent: Entity = NonEntity ) extends TypeAlias diff --git a/doc-tool/src/dotty/tools/dottydoc/staticsite/tags.scala b/doc-tool/src/dotty/tools/dottydoc/staticsite/tags.scala index cd2ea587d..bc4a74c4f 100644 --- a/doc-tool/src/dotty/tools/dottydoc/staticsite/tags.scala +++ b/doc-tool/src/dotty/tools/dottydoc/staticsite/tags.scala @@ -180,6 +180,7 @@ object tags { override def render(ctx: TemplateContext, nodes: LNode*): AnyRef = (nodes(0).render(ctx), nodes(1).render(ctx)) match { case (t: Title, parent: String) => renderTitle(t, parent) + case (t: Title, _) => renderTitle(t, "./") // file is in top dir case _ => null } } diff --git a/docs/docs/internals/syntax.md b/docs/docs/internals/syntax.md index b7d5936c2..7f06cdc2a 100644 --- a/docs/docs/internals/syntax.md +++ b/docs/docs/internals/syntax.md @@ -126,7 +126,7 @@ InfixType ::= RefinedType {id [nl] RefinedType} RefinedType ::= WithType {[nl] Refinement} RefinedTypeTree(t, ds) WithType ::= AnnotType {‘with’ AnnotType} (deprecated) AnnotType ::= SimpleType {Annotation} Annotated(t, annot) -SimpleType ::= SimpleType (TypeArgs | NamedTypeArgs) AppliedTypeTree(t, args) +SimpleType ::= SimpleType TypeArgs AppliedTypeTree(t, args) | SimpleType ‘#’ id Select(t, name) | StableId | Path ‘.’ ‘type’ SingletonTypeTree(p) @@ -240,7 +240,7 @@ ArgumentPatterns ::= ‘(’ [Patterns] ‘)’ ### Type and Value Parameters ```ebnf ClsTypeParamClause::= ‘[’ ClsTypeParam {‘,’ ClsTypeParam} ‘]’ -ClsTypeParam ::= {Annotation} [{Modifier} type] [‘+’ | ‘-’] TypeDef(Modifiers, name, tparams, bounds) +ClsTypeParam ::= {Annotation} [‘+’ | ‘-’] TypeDef(Modifiers, name, tparams, bounds) id [HkTypeParamClause] TypeParamBounds Bound(below, above, context) DefTypeParamClause::= ‘[’ DefTypeParam {‘,’ DefTypeParam} ‘]’ diff --git a/library/src/dotty/DottyPredef.scala b/library/src/dotty/DottyPredef.scala index c7cf2a906..e78fa9239 100644 --- a/library/src/dotty/DottyPredef.scala +++ b/library/src/dotty/DottyPredef.scala @@ -1,14 +1,11 @@ package dotty -import scala.reflect.runtime.universe.TypeTag import scala.reflect.ClassTag import scala.Predef.??? import scala.collection.Seq /** unimplemented implicit for TypeTag */ object DottyPredef { - implicit def typeTag[T]: TypeTag[T] = ??? - /** A fall-back implicit to compare values of any types. * The compiler will restrict implicit instances of `eqAny`. An instance * `eqAny[T, U]` is _valid_ if `T <: U` or `U <: T` or both `T` and `U` are @@ -39,4 +36,24 @@ object DottyPredef { implicit def eqNumFloat : Eq[Number, Float] = Eq implicit def eqDoubleNum: Eq[Double, Number] = Eq implicit def eqNumDouble: Eq[Number, Double] = Eq + + /** A class for implicit values that can serve as implicit conversions + * The implicit resolution algorithm will act as if there existed + * the additional implicit definition: + * + * def $implicitConversion[T, U](x: T)(c: ImplicitConverter[T, U]): U = c(x) + * + * However, the presence of this definition would slow down implicit search since + * its outermost type matches any pair of types. Therefore, implicit search + * contains a special case in `Implicits#discardForView` which emulates the + * conversion in a more efficient way. + * + * Note that this is a SAM class - function literals are automatically converted + * to `ImplicitConverter` values. + * + * Also note that in bootstrapped dotty, `Predef.<:<` should inherit from + * `ImplicitConverter`. This would cut the number of special cases in + * `discardForView` from two to one. + */ + abstract class ImplicitConverter[-T, +U] extends Function1[T, U] } diff --git a/tests/pos/contextbounds-implicits-new.scala b/tests/disabled/scalac-dependent/pos/contextbounds-implicits-new.scala index 8389d1332..8389d1332 100644 --- a/tests/pos/contextbounds-implicits-new.scala +++ b/tests/disabled/scalac-dependent/pos/contextbounds-implicits-new.scala diff --git a/tests/pos/spec-doubledef-new.scala b/tests/disabled/scalac-dependent/pos/spec-doubledef-new.scala index de438d6e9..de438d6e9 100644 --- a/tests/pos/spec-doubledef-new.scala +++ b/tests/disabled/scalac-dependent/pos/spec-doubledef-new.scala diff --git a/tests/pos-scala2/t7688.scala b/tests/disabled/scalac-dependent/pos/t7688.scala index 5a846b97e..5a846b97e 100644 --- a/tests/pos-scala2/t7688.scala +++ b/tests/disabled/scalac-dependent/pos/t7688.scala diff --git a/tests/pos/t8187.scala b/tests/disabled/scalac-dependent/pos/t8187.scala index 84b8cd0f4..84b8cd0f4 100644 --- a/tests/pos/t8187.scala +++ b/tests/disabled/scalac-dependent/pos/t8187.scala diff --git a/tests/run/bytecodecs.scala b/tests/disabled/scalac-dependent/run/bytecodecs.scala index 454958dfa..454958dfa 100644 --- a/tests/run/bytecodecs.scala +++ b/tests/disabled/scalac-dependent/run/bytecodecs.scala diff --git a/tests/run/var-arity-class-symbol.scala b/tests/disabled/scalac-dependent/run/var-arity-class-symbol.scala index 2a7d32987..2a7d32987 100644 --- a/tests/run/var-arity-class-symbol.scala +++ b/tests/disabled/scalac-dependent/run/var-arity-class-symbol.scala diff --git a/tests/neg/customArgs/typers.scala b/tests/neg/customArgs/typers.scala index 49742ebbd..9432ab039 100644 --- a/tests/neg/customArgs/typers.scala +++ b/tests/neg/customArgs/typers.scala @@ -30,7 +30,7 @@ object typers { } type L[X] = scala.collection.immutable.List[X] - type M[X, Y] <: scala.collection.immutable.Map[X, Y] // error: only classes can have declared but undefined members + type M[X, Y] <: scala.collection.immutable.Map[X, Y] // old-error: only classes can have declared but undefined members object hk { def f(x: L) // error: missing type parameter diff --git a/tests/neg/falseView.scala b/tests/neg/falseView.scala new file mode 100644 index 000000000..613abe3f1 --- /dev/null +++ b/tests/neg/falseView.scala @@ -0,0 +1,7 @@ +object Test { + + private implicit val xs: Map[String, Int] = ??? + + val x: Int = "abc" // error + +} diff --git a/tests/neg/i1050c.scala b/tests/neg/i1050c.scala index 19570eb83..ecfaa3ea3 100644 --- a/tests/neg/i1050c.scala +++ b/tests/neg/i1050c.scala @@ -27,7 +27,8 @@ object Tiark4 { v.brand("boom!") } object V { // error: cannot be instantiated - type Y >: Any <: Nothing // error: only classes can have declared but undefined members + type Y >: Any <: Nothing // old-error: only classes can have declared but undefined members + type Z } object Tiark5 { trait A { type L <: Nothing } diff --git a/tests/neg/i2030.scala b/tests/neg/i2030.scala new file mode 100644 index 000000000..2d049f4e6 --- /dev/null +++ b/tests/neg/i2030.scala @@ -0,0 +1,5 @@ +// This used to take ~12s, the check should be that +// it runs in reasonable time (i.e. instantaneous). +object a { + val x: String | Int = 'a // error +} diff --git a/tests/neg/namedTypeParams.scala b/tests/neg/namedTypeParams.scala new file mode 100644 index 000000000..75bb1cd7e --- /dev/null +++ b/tests/neg/namedTypeParams.scala @@ -0,0 +1,12 @@ +class C[T] +class D[type T] // error: identifier expected, but `type` found + +object Test { + + val x: C[T = Int] = // error: ']' expected, but `=` found // error + new C[T = Int] // error: ']' expected, but `=` found // error + + class E extends C[T = Int] // error: ']' expected, but `=` found // error + class F extends C[T = Int]() // error: ']' expected, but `=` found // error + +} diff --git a/tests/pickling/innerclass.scala b/tests/pickling/innerclass.scala new file mode 100644 index 000000000..5881cf6ed --- /dev/null +++ b/tests/pickling/innerclass.scala @@ -0,0 +1,3 @@ +trait Foo { + class Inner(x: Int = 42) +} diff --git a/tests/pos/typerep-stephane.scala b/tests/pos-scala2/typerep-stephane.scala index 2cb899591..2cb899591 100644 --- a/tests/pos/typerep-stephane.scala +++ b/tests/pos-scala2/typerep-stephane.scala diff --git a/tests/pos/viewtest1.scala b/tests/pos-scala2/viewtest1.scala index 38945ad2f..38945ad2f 100644 --- a/tests/pos/viewtest1.scala +++ b/tests/pos-scala2/viewtest1.scala diff --git a/tests/pos/i2056.scala b/tests/pos/i2056.scala new file mode 100644 index 000000000..c4d020fb6 --- /dev/null +++ b/tests/pos/i2056.scala @@ -0,0 +1,13 @@ +object Test { + inline def crash() = { + try { + println("hi") + } catch { + case e: Exception => + } + } + + def main(args: Array[String]): Unit = { + crash() + } +} diff --git a/tests/pos/t0786.scala b/tests/pos/t0786.scala index b320de0ed..9346afdff 100644 --- a/tests/pos/t0786.scala +++ b/tests/pos/t0786.scala @@ -15,7 +15,7 @@ object ImplicitProblem { def eval = f(nullval[T]).eval + 1 } - def depth[T](n: T)(implicit ev: T => Rep[T]) = n.eval + def depth[T](n: T)(implicit ev: T => Rep[T]) = ev(n).eval def main(args: Array[String]): Unit = { println(depth(nullval[M[Int]])) // (1) this works diff --git a/tests/pos/t2421_delitedsl.scala b/tests/pos/t2421_delitedsl.scala index 22f1ecd85..bde3593c9 100644 --- a/tests/pos/t2421_delitedsl.scala +++ b/tests/pos/t2421_delitedsl.scala @@ -1,6 +1,9 @@ trait DeliteDSL { abstract class <~<[-From, +To] extends (From => To) + implicit def trivial[A]: A <~< A = new (A <~< A) {def apply(x: A) = x} + implicit def convert_<-<[A, B](x: A)(implicit ev: A <~< B): B = ev(x) + trait Forcible[T] object Forcible { diff --git a/tests/repl/errmsgs.check b/tests/repl/errmsgs.check index d7a230e61..4e89a16a5 100644 --- a/tests/repl/errmsgs.check +++ b/tests/repl/errmsgs.check @@ -86,7 +86,7 @@ scala> val x: List[Int] = "foo" :: List(1) | required: Int | scala> { def f: Int = g; val x: Int = 1; def g: Int = 5; } --- [E039] Reference Error: <console> ------------------------------------------- +-- [E038] Reference Error: <console> ------------------------------------------- 5 |{ def f: Int = g; val x: Int = 1; def g: Int = 5; } | ^ | `g` is a forward reference extending over the definition of `x` diff --git a/tests/repl/overrides.check b/tests/repl/overrides.check index 2424c80ce..0fbd3d0e3 100644 --- a/tests/repl/overrides.check +++ b/tests/repl/overrides.check @@ -1,5 +1,5 @@ scala> class B { override def foo(i: Int): Unit = {}; } --- [E037] Reference Error: <console> ------------------------------------------- +-- [E036] Reference Error: <console> ------------------------------------------- 4 |class B { override def foo(i: Int): Unit = {}; } | ^ | method foo overrides nothing @@ -8,7 +8,7 @@ longer explanation available when compiling with `-explain` scala> class A { def foo: Unit = {}; } defined class A scala> class B extends A { override def foo(i: Int): Unit = {}; } --- [E038] Reference Error: <console> ------------------------------------------- +-- [E037] Reference Error: <console> ------------------------------------------- 5 |class B extends A { override def foo(i: Int): Unit = {}; } | ^ | method foo has a different signature than the overridden declaration diff --git a/tests/run/builder.check b/tests/run/builder.check index 48f7d9253..04048dfcc 100644 --- a/tests/run/builder.check +++ b/tests/run/builder.check @@ -1 +1 @@ -Table(Row(Cell(A1), Cell(B1)), Row(Cell(A2), Cell(B2))) +Table(Row(Cell(top left), Cell(top right)), Row(Cell(botttom left), Cell(bottom right))) diff --git a/tests/run/builder.scala b/tests/run/builder.scala index 532a95071..d09e9f2c8 100644 --- a/tests/run/builder.scala +++ b/tests/run/builder.scala @@ -12,9 +12,7 @@ class Row { override def toString = cells.mkString("Row(", ", ", ")") } -class Cell(elem: String) { - override def toString = s"Cell($elem)" -} +case class Cell(elem: String) object Test { @@ -36,12 +34,12 @@ object Test { val data = table { row { - cell("A1") - cell("B1") + cell("top left") + cell("top right") } row { - cell("A2") - cell("B2") + cell("botttom left") + cell("bottom right") } } diff --git a/tests/run/iterator-from.scala b/tests/run/iterator-from.scala index 4f403680c..c7c0f9809 100644 --- a/tests/run/iterator-from.scala +++ b/tests/run/iterator-from.scala @@ -11,7 +11,9 @@ object Test extends dotty.runtime.LegacyApp { val maxKey = 50 val maxValue = 50 - def testSet[A <% Ordered[A]](set: SortedSet[A], list: List[A]): Unit = { + implicit def convertIfView[A](x: A)(implicit view: A => Ordered[A]): Ordered[A] = view(x) + + def testSet[A: Ordering](set: SortedSet[A], list: List[A]): Unit = { val distinctSorted = list.distinct.sorted assertEquals("Set size wasn't the same as list sze", set.size, distinctSorted.size) @@ -24,7 +26,7 @@ object Test extends dotty.runtime.LegacyApp { } } - def testMap[A <% Ordered[A], B](map: SortedMap[A, B], list: List[(A, B)]): Unit = { + def testMap[A: Ordering, B](map: SortedMap[A, B], list: List[(A, B)]): Unit = { val distinctSorted = distinctByKey(list).sortBy(_._1) assertEquals("Map size wasn't the same as list sze", map.size, distinctSorted.size) diff --git a/tests/run/puzzler54.scala b/tests/run/puzzler54.scala new file mode 100644 index 000000000..9dd4cbb47 --- /dev/null +++ b/tests/run/puzzler54.scala @@ -0,0 +1,13 @@ +// Scala Puzzler 54 +object Test { + case class Card(number: Int, suit: String = "clubs") { + val value = (number % 13) + 1 // ace = 1, king = 13 + def isInDeck(implicit deck: List[Card]) = deck contains this + } + + def main(args: Array[String]) = { + implicit val deck = List(Card(1, "clubs")) + implicit def intToCard(n: Int): Card = Card(n) + assert(1.isInDeck) + } +} diff --git a/tests/run/t8280.check b/tests/run/t8280.check index 44c51f5aa..b5885df48 100644 --- a/tests/run/t8280.check +++ b/tests/run/t8280.check @@ -1,7 +1,6 @@ -Int -Int Long Int Int Int Int +Int diff --git a/tests/run/t8280.scala b/tests/run/t8280.scala index f433dcc32..5fcbad0a3 100644 --- a/tests/run/t8280.scala +++ b/tests/run/t8280.scala @@ -37,7 +37,8 @@ object Moop1 { implicit object f1 extends (Int => String) { def apply(x: Int): String = "Int" } implicit val f2: Long => String = _ => "Long" - println(5: String) + //println(5: String) + // This picked f1 before, but is now disallowed since subtypes of functions are no longer implicit conversions } } @@ -73,14 +74,14 @@ object Moop3 { // Dotty deviation. This fails for Dotty with ambiguity error for similar reasons as ob1. } object ob2 { - implicit val f1: Int => String = _ => "Int" + implicit val f1: ImplicitConverter[Int, String] = _ => "Int" implicit def f2(x: Long): String = "Long" println(5: String) } object ob3 { - implicit val f1: Int => String = _ => "Int" - implicit val f2: Long => String = _ => "Long" + implicit val f1: ImplicitConverter[Int, String] = _ => "Int" + implicit val f2: ImplicitConverter[Long, String] = _ => "Long" println(5: String) } diff --git a/tests/tasty/default-param-interface.scala b/tests/tasty/default-param-interface.scala new file mode 100644 index 000000000..919f4b627 --- /dev/null +++ b/tests/tasty/default-param-interface.scala @@ -0,0 +1,3 @@ +trait Foo { + def newName(prefix: String = "foo"): String +} |