aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/src/dotty/tools/FatalError.scala3
-rw-r--r--compiler/src/dotty/tools/backend/jvm/CollectEntryPoints.scala12
-rw-r--r--compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala2
-rw-r--r--compiler/src/dotty/tools/backend/jvm/LabelDefs.scala1
-rw-r--r--compiler/src/dotty/tools/dotc/Compiler.scala4
-rw-r--r--compiler/src/dotty/tools/dotc/ast/TreeInfo.scala22
-rw-r--r--compiler/src/dotty/tools/dotc/ast/Trees.scala7
-rw-r--r--compiler/src/dotty/tools/dotc/ast/tpd.scala4
-rw-r--r--compiler/src/dotty/tools/dotc/ast/untpd.scala1
-rw-r--r--compiler/src/dotty/tools/dotc/config/Config.scala13
-rw-r--r--compiler/src/dotty/tools/dotc/config/JavaPlatform.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/config/ScalaSettings.scala4
-rw-r--r--compiler/src/dotty/tools/dotc/config/Settings.scala1
-rw-r--r--compiler/src/dotty/tools/dotc/core/Constraint.scala6
-rw-r--r--compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala27
-rw-r--r--compiler/src/dotty/tools/dotc/core/Decorators.scala12
-rw-r--r--compiler/src/dotty/tools/dotc/core/Definitions.scala6
-rw-r--r--compiler/src/dotty/tools/dotc/core/Denotations.scala18
-rw-r--r--compiler/src/dotty/tools/dotc/core/Flags.scala12
-rw-r--r--compiler/src/dotty/tools/dotc/core/NameOps.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala8
-rw-r--r--compiler/src/dotty/tools/dotc/core/StdNames.scala3
-rw-r--r--compiler/src/dotty/tools/dotc/core/SymDenotations.scala23
-rw-r--r--compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/core/Symbols.scala13
-rw-r--r--compiler/src/dotty/tools/dotc/core/TypeApplications.scala61
-rw-r--r--compiler/src/dotty/tools/dotc/core/TypeComparer.scala55
-rw-r--r--compiler/src/dotty/tools/dotc/core/TypeErasure.scala16
-rw-r--r--compiler/src/dotty/tools/dotc/core/TypeOps.scala14
-rw-r--r--compiler/src/dotty/tools/dotc/core/Types.scala173
-rw-r--r--compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala10
-rw-r--r--compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala7
-rw-r--r--compiler/src/dotty/tools/dotc/core/unpickleScala2/PickleBuffer.scala19
-rw-r--r--compiler/src/dotty/tools/dotc/core/unpickleScala2/PickleFormat.scala227
-rw-r--r--compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Flags.scala109
-rw-r--r--compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala10
-rw-r--r--compiler/src/dotty/tools/dotc/parsing/CharArrayReader.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala3
-rw-r--r--compiler/src/dotty/tools/dotc/parsing/JavaScanners.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/parsing/MarkupParserCommon.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/parsing/MarkupParsers.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/parsing/Parsers.scala34
-rw-r--r--compiler/src/dotty/tools/dotc/parsing/Scanners.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/parsing/SymbolicXMLBuilder.scala4
-rw-r--r--compiler/src/dotty/tools/dotc/parsing/Utility.scala5
-rw-r--r--compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala6
-rw-r--r--compiler/src/dotty/tools/dotc/printing/SyntaxHighlighting.scala19
-rw-r--r--compiler/src/dotty/tools/dotc/reporting/MessageRendering.scala44
-rw-r--r--compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java5
-rw-r--r--compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala62
-rw-r--r--compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala8
-rw-r--r--compiler/src/dotty/tools/dotc/transform/CollectEntryPoints.scala6
-rw-r--r--compiler/src/dotty/tools/dotc/transform/ElimByName.scala4
-rw-r--r--compiler/src/dotty/tools/dotc/transform/ElimRepeated.scala25
-rw-r--r--compiler/src/dotty/tools/dotc/transform/Erasure.scala13
-rw-r--r--compiler/src/dotty/tools/dotc/transform/ExpandSAMs.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala6
-rw-r--r--compiler/src/dotty/tools/dotc/transform/FirstTransform.scala21
-rw-r--r--compiler/src/dotty/tools/dotc/transform/FullParameterization.scala19
-rw-r--r--compiler/src/dotty/tools/dotc/transform/LambdaLift.scala4
-rw-r--r--compiler/src/dotty/tools/dotc/transform/LazyVals.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/transform/ParamForwarding.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala6
-rw-r--r--compiler/src/dotty/tools/dotc/transform/TreeChecker.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Applications.scala56
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Checking.scala28
-rw-r--r--compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala12
-rw-r--r--compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala4
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Implicits.scala39
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Namer.scala184
-rw-r--r--compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala79
-rw-r--r--compiler/src/dotty/tools/dotc/typer/ReTyper.scala4
-rw-r--r--compiler/src/dotty/tools/dotc/typer/RefChecks.scala20
-rw-r--r--compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala28
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Typer.scala88
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Variances.scala4
-rw-r--r--compiler/src/dotty/tools/dotc/util/CommentParsing.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/util/FreshNameCreator.scala5
-rw-r--r--compiler/src/dotty/tools/dotc/util/ShowPickled.scala4
-rw-r--r--compiler/src/dotty/tools/dotc/util/SourcePosition.scala8
-rw-r--r--compiler/src/dotty/tools/io/ClassPath.scala4
-rw-r--r--compiler/src/dotty/tools/package.scala3
-rw-r--r--compiler/test/dotc/tests.scala6
-rw-r--r--compiler/test/dotty/partest/DPConsoleRunner.scala3
-rw-r--r--compiler/test/dotty/tools/dotc/parsing/ModifiersParsingTest.scala3
-rw-r--r--compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala95
-rw-r--r--compiler/test/dotty/tools/dotc/reporting/TestReporter.scala1
-rw-r--r--doc-tool/resources/_layouts/api-page.html15
-rw-r--r--doc-tool/resources/css/dottydoc.css6
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/core/DocASTPhase.scala14
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/core/transform.scala1
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/model/JavaConverters.scala1
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/model/comment/CommentParser.scala3
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/model/entities.scala2
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/model/factories.scala18
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/model/internal.scala1
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/staticsite/tags.scala1
-rw-r--r--docs/docs/internals/syntax.md4
-rw-r--r--library/src/dotty/DottyPredef.scala23
-rw-r--r--sbt-bridge/sbt-test/compilerReporter/simple/project/Reporter.scala3
-rw-r--r--sbt-bridge/src/xsbt/DelegatingReporter.scala41
-rw-r--r--tests/disabled/pos/depmet_implicit_oopsla_session_simpler.scala (renamed from tests/pending/pos/depmet_implicit_oopsla_session_simpler.scala)3
-rw-r--r--tests/disabled/scalac-dependent/pos/contextbounds-implicits-new.scala (renamed from tests/pos/contextbounds-implicits-new.scala)0
-rw-r--r--tests/disabled/scalac-dependent/pos/spec-doubledef-new.scala (renamed from tests/pos/spec-doubledef-new.scala)0
-rw-r--r--tests/disabled/scalac-dependent/pos/t7688.scala (renamed from tests/pos-scala2/t7688.scala)0
-rw-r--r--tests/disabled/scalac-dependent/pos/t8187.scala (renamed from tests/pos/t8187.scala)0
-rw-r--r--tests/disabled/scalac-dependent/run/bytecodecs.scala (renamed from tests/run/bytecodecs.scala)0
-rw-r--r--tests/disabled/scalac-dependent/run/var-arity-class-symbol.scala (renamed from tests/run/var-arity-class-symbol.scala)0
-rw-r--r--tests/neg/customArgs/typers.scala2
-rw-r--r--tests/neg/falseView.scala7
-rw-r--r--tests/neg/i1050c.scala3
-rw-r--r--tests/neg/i1706.scala3
-rw-r--r--tests/neg/i2030.scala5
-rw-r--r--tests/neg/i2066.scala27
-rw-r--r--tests/neg/illegal-depmeth.scala13
-rw-r--r--tests/neg/namedTypeParams.scala12
-rw-r--r--tests/neg/t1569-failedAvoid.scala9
-rw-r--r--tests/pending/pos/depmet_implicit_oopsla_session_2.scala5
-rw-r--r--tests/pickling/default-param-interface.scala3
-rw-r--r--tests/pickling/i982.scala (renamed from tests/tasty/i982.scala)0
-rw-r--r--tests/pickling/innerclass.scala3
-rw-r--r--tests/pos-java-interop/varargsOverride/Base.java5
-rw-r--r--tests/pos-java-interop/varargsOverride/Sub.scala3
-rw-r--r--tests/pos-scala2/typerep-stephane.scala (renamed from tests/pos/typerep-stephane.scala)0
-rw-r--r--tests/pos-scala2/viewtest1.scala (renamed from tests/pos/viewtest1.scala)0
-rw-r--r--tests/pos/depmet_implicit_norm_ret.scala (renamed from tests/pending/pos/depmet_implicit_norm_ret.scala)0
-rw-r--r--tests/pos/erased-lub-2.scala15
-rw-r--r--tests/pos/i2056.scala13
-rw-r--r--tests/pos/i2064.scala15
-rw-r--r--tests/pos/i2066.scala15
-rw-r--r--tests/pos/i2071.scala7
-rw-r--r--tests/pos/param-depmeth.scala15
-rw-r--r--tests/pos/t0786.scala2
-rw-r--r--tests/pos/t1569.scala12
-rw-r--r--tests/pos/t2421_delitedsl.scala3
-rw-r--r--tests/pos/t5070.scala23
-rw-r--r--tests/pos/t5643.scala19
-rw-r--r--tests/repl/errmsgs.check2
-rw-r--r--tests/repl/overrides.check4
-rw-r--r--tests/run/HLists-nonvariant.check8
-rw-r--r--tests/run/HLists-nonvariant.scala78
-rw-r--r--tests/run/HLists.check8
-rw-r--r--tests/run/HLists.scala78
-rw-r--r--tests/run/builder.check2
-rw-r--r--tests/run/builder.scala12
-rw-r--r--tests/run/hmap-covariant.scala97
-rw-r--r--tests/run/i1960.scala8
-rw-r--r--tests/run/i2004.check1
-rw-r--r--tests/run/i2004.scala11
-rw-r--r--tests/run/i2077.check1
-rw-r--r--tests/run/i2077.scala10
-rw-r--r--tests/run/iterator-from.scala6
-rw-r--r--tests/run/puzzler54.scala13
-rw-r--r--tests/run/t8280.check3
-rw-r--r--tests/run/t8280.scala9
155 files changed, 1891 insertions, 736 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..abcbbbb83 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}
@@ -50,7 +49,7 @@ class CollectEntryPoints extends MiniPhaseTransform {
object CollectEntryPoints{
def isJavaMainMethod(sym: Symbol)(implicit ctx: Context) = {
(sym.name == nme.main) && (sym.info match {
- case r@MethodType(_, List(defn.ArrayOf(t))) =>
+ case r@MethodTpe(_, List(defn.ArrayOf(t)), _) =>
(t.widenDealias =:= defn.StringType) && (
r.resultType.widenDealias =:= defn.UnitType)
case _ => false
@@ -82,9 +81,8 @@ object CollectEntryPoints{
val possibles = if (sym.flags is Flags.Module) (toDenot(sym).info nonPrivateMember nme.main).alternatives else Nil
val hasApproximate = possibles exists { m =>
m.info match {
- case MethodType(_, p :: Nil) =>
- p.typeSymbol == defn.ArrayClass
- case _ => false
+ case MethodTpe(_, p :: Nil, _) => p.typeSymbol == defn.ArrayClass
+ case _ => false
}
}
// At this point it's a module with a main-looking method, so either succeed or warn that it isn't.
@@ -109,8 +107,8 @@ object CollectEntryPoints{
toDenot(m.symbol).info match {
case t: PolyType =>
fail("main methods cannot be generic.")
- case t@MethodType(paramNames, paramTypes) =>
- if (t.resultType :: paramTypes exists (_.typeSymbol.isAbstractType))
+ case MethodTpe(paramNames, paramTypes, resultType) =>
+ if (resultType :: paramTypes exists (_.typeSymbol.isAbstractType))
fail("main methods cannot refer to type parameters or abstract types.", m.symbol.pos)
else
isJavaMainMethod(m.symbol) || fail("main method must have exact signature (Array[String])Unit", m.symbol.pos)
diff --git a/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala b/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala
index 51fa15706..77e979e4d 100644
--- a/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala
+++ b/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala
@@ -531,7 +531,7 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma
tree match {
case Apply(fun, args) =>
fun.tpe.widen match {
- case MethodType(names, _) =>
+ case MethodType(names) =>
names zip args
}
}
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/Compiler.scala b/compiler/src/dotty/tools/dotc/Compiler.scala
index 1d319242b..f413fc902 100644
--- a/compiler/src/dotty/tools/dotc/Compiler.scala
+++ b/compiler/src/dotty/tools/dotc/Compiler.scala
@@ -48,9 +48,9 @@ class Compiler {
List(new Pickler), // Generate TASTY info
List(new FirstTransform, // Some transformations to put trees into a canonical form
new CheckReentrant), // Internal use only: Check that compiled program has no data races involving global vars
- List(new RefChecks, // Various checks mostly related to abstract members and overriding
- new CheckStatic, // Check restrictions that apply to @static members
+ List(new CheckStatic, // Check restrictions that apply to @static members
new ElimRepeated, // Rewrite vararg parameters and arguments
+ new RefChecks, // Various checks mostly related to abstract members and overriding
new NormalizeFlags, // Rewrite some definition flags
new ExtensionMethods, // Expand methods of value classes with extension methods
new ExpandSAMs, // Expand single abstract method closures to anonymous classes
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/tpd.scala b/compiler/src/dotty/tools/dotc/ast/tpd.scala
index 458e94b6e..cbb256dd0 100644
--- a/compiler/src/dotty/tools/dotc/ast/tpd.scala
+++ b/compiler/src/dotty/tools/dotc/ast/tpd.scala
@@ -185,12 +185,12 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
}
def valueParamss(tp: Type): (List[List[TermSymbol]], Type) = tp match {
- case tp @ MethodType(paramNames, paramTypes) =>
+ case tp: MethodType =>
def valueParam(name: TermName, info: Type): TermSymbol = {
val maybeImplicit = if (tp.isInstanceOf[ImplicitMethodType]) Implicit else EmptyFlags
ctx.newSymbol(sym, name, TermParam | maybeImplicit, info)
}
- val params = (paramNames, paramTypes).zipped.map(valueParam)
+ val params = (tp.paramNames, tp.paramTypes).zipped.map(valueParam)
val (paramss, rtp) = valueParamss(tp.instantiate(params map (_.termRef)))
(params :: paramss, rtp)
case tp => (Nil, tp.widenExpr)
diff --git a/compiler/src/dotty/tools/dotc/ast/untpd.scala b/compiler/src/dotty/tools/dotc/ast/untpd.scala
index 99bc3240f..8ca91590f 100644
--- a/compiler/src/dotty/tools/dotc/ast/untpd.scala
+++ b/compiler/src/dotty/tools/dotc/ast/untpd.scala
@@ -149,6 +149,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
def is(fs: FlagSet): Boolean = flags is fs
def is(fc: FlagConjunction): Boolean = flags is fc
+ def is(fc: FlagSet, butNot: FlagSet): Boolean = flags.is(fc, butNot = butNot)
def | (fs: FlagSet): Modifiers = withFlags(flags | fs)
def & (fs: FlagSet): Modifiers = withFlags(flags & fs)
diff --git a/compiler/src/dotty/tools/dotc/config/Config.scala b/compiler/src/dotty/tools/dotc/config/Config.scala
index 119af9483..903efd794 100644
--- a/compiler/src/dotty/tools/dotc/config/Config.scala
+++ b/compiler/src/dotty/tools/dotc/config/Config.scala
@@ -75,10 +75,23 @@ object Config {
/** If this flag is set, take the fast path when comparing same-named type-aliases and types */
final val fastPathForRefinedSubtype = true
+ /** If this flag is set, and we compute `T1 { X = S1 }` & `T2 { X = S2 }` as a new
+ * upper bound of a constrained parameter, try to align the refinements by computing
+ * `S1 =:= S2` (which might instantiate type parameters).
+ * This rule is contentious because it cuts the constraint set.
+ *
+ * For more info, see the comment in `TypeComparer#distributeAnd`.
+ */
+ final val alignArgsInAnd = true
+
/** If this flag is set, higher-kinded applications are checked for validity
*/
final val checkHKApplications = false
+ /** If this flag is set, method types are checked for valid parameter references
+ */
+ final val checkMethodTypes = false
+
/** The recursion depth for showing a summarized string */
final val summarizeDepth = 2
diff --git a/compiler/src/dotty/tools/dotc/config/JavaPlatform.scala b/compiler/src/dotty/tools/dotc/config/JavaPlatform.scala
index 59201687a..8bc18c387 100644
--- a/compiler/src/dotty/tools/dotc/config/JavaPlatform.scala
+++ b/compiler/src/dotty/tools/dotc/config/JavaPlatform.scala
@@ -23,7 +23,7 @@ class JavaPlatform extends Platform {
// The given symbol is a method with the right name and signature to be a runnable java program.
def isJavaMainMethod(sym: SymDenotation)(implicit ctx: Context) =
(sym.name == nme.main) && (sym.info match {
- case t@MethodType(_, defn.ArrayOf(el) :: Nil) => el =:= defn.StringType && (t.resultType isRef defn.UnitClass)
+ case MethodTpe(_, defn.ArrayOf(el) :: Nil, restpe) => el =:= defn.StringType && (restpe isRef defn.UnitClass)
case _ => false
})
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 c2763cdf0..264388c03 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 scala.annotation.tailrec
diff --git a/compiler/src/dotty/tools/dotc/core/Constraint.scala b/compiler/src/dotty/tools/dotc/core/Constraint.scala
index c99b748b7..50136a26c 100644
--- a/compiler/src/dotty/tools/dotc/core/Constraint.scala
+++ b/compiler/src/dotty/tools/dotc/core/Constraint.scala
@@ -111,12 +111,6 @@ abstract class Constraint extends Showable {
*/
def replace(param: PolyParam, tp: Type)(implicit ctx: Context): This
- /** Narrow one of the bounds of type parameter `param`
- * If `isUpper` is true, ensure that `param <: `bound`, otherwise ensure
- * that `param >: bound`.
- */
- def narrowBound(param: PolyParam, bound: Type, isUpper: Boolean)(implicit ctx: Context): This
-
/** Is entry associated with `pt` removable? This is the case if
* all type parameters of the entry are associated with type variables
* which have their `inst` fields set.
diff --git a/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala b/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala
index 3aa20f15b..2a1f4ee6e 100644
--- a/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala
+++ b/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala
@@ -44,6 +44,13 @@ trait ConstraintHandling {
try op finally alwaysFluid = saved
}
+ /** If set, align arguments `S1`, `S2`when taking the glb
+ * `T1 { X = S1 } & T2 { X = S2 }` of a constraint upper bound for some type parameter.
+ * Aligning means computing `S1 =:= S2` which may change the current constraint.
+ * See note in TypeComparer#distributeAnd.
+ */
+ protected var homogenizeArgs = false
+
/** We are currently comparing polytypes. Used as a flag for
* optimization: when `false`, no need to do an expensive `pruneLambdaParams`
*/
@@ -64,7 +71,8 @@ trait ConstraintHandling {
}
if (Config.checkConstraintsSeparated)
assert(!occursIn(bound), s"$param occurs in $bound")
- val c1 = constraint.narrowBound(param, bound, isUpper)
+ val newBound = narrowedBound(param, bound, isUpper)
+ val c1 = constraint.updateEntry(param, newBound)
(c1 eq constraint) || {
constraint = c1
val TypeBounds(lo, hi) = constraint.entry(param)
@@ -72,6 +80,20 @@ trait ConstraintHandling {
}
}
+ /** Narrow one of the bounds of type parameter `param`
+ * If `isUpper` is true, ensure that `param <: `bound`, otherwise ensure
+ * that `param >: bound`.
+ */
+ def narrowedBound(param: PolyParam, bound: Type, isUpper: Boolean)(implicit ctx: Context): TypeBounds = {
+ val oldBounds @ TypeBounds(lo, hi) = constraint.nonParamBounds(param)
+ val saved = homogenizeArgs
+ homogenizeArgs = Config.alignArgsInAnd
+ try
+ if (isUpper) oldBounds.derivedTypeBounds(lo, hi & bound)
+ else oldBounds.derivedTypeBounds(lo | bound, hi)
+ finally homogenizeArgs = saved
+ }
+
protected def addUpperBound(param: PolyParam, bound: Type): Boolean = {
def description = i"constraint $param <: $bound to\n$constraint"
if (bound.isRef(defn.NothingClass) && ctx.typerState.isGlobalCommittable) {
@@ -253,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 79e97becb..4d4350f98 100644
--- a/compiler/src/dotty/tools/dotc/core/Definitions.scala
+++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala
@@ -10,7 +10,6 @@ import scala.collection.{ mutable, immutable }
import PartialFunction._
import collection.mutable
import util.common.alwaysZero
-import scala.reflect.api.{ Universe => ApiUniverse }
object Definitions {
@@ -300,6 +299,8 @@ class Definitions {
lazy val ScalaPredefModuleRef = ctx.requiredModuleRef("scala.Predef")
def ScalaPredefModule(implicit ctx: Context) = ScalaPredefModuleRef.symbol
+ lazy val Predef_ConformsR = ScalaPredefModule.requiredClass("$less$colon$less").typeRef
+ def Predef_Conforms(implicit ctx: Context) = Predef_ConformsR.symbol
lazy val Predef_conformsR = ScalaPredefModule.requiredMethodRef("$conforms")
def Predef_conforms(implicit ctx: Context) = Predef_conformsR.symbol
lazy val Predef_classOfR = ScalaPredefModule.requiredMethodRef("classOf")
@@ -337,6 +338,8 @@ class Definitions {
def DottyPredefModule(implicit ctx: Context) = DottyPredefModuleRef.symbol
def Predef_eqAny(implicit ctx: Context) = DottyPredefModule.requiredMethod(nme.eqAny)
+ lazy val Predef_ImplicitConverterR = DottyPredefModule.requiredClass("ImplicitConverter").typeRef
+ def Predef_ImplicitConverter(implicit ctx: Context) = Predef_ImplicitConverterR.symbol
lazy val DottyArraysModuleRef = ctx.requiredModuleRef("dotty.runtime.Arrays")
def DottyArraysModule(implicit ctx: Context) = DottyArraysModuleRef.symbol
@@ -352,6 +355,7 @@ class Definitions {
enterCompleteClassSymbol(
ScalaPackageClass, tpnme.Singleton, PureInterfaceCreationFlags | Final,
List(AnyClass.typeRef), EmptyScope)
+ def SingletonType = SingletonClass.typeRef
lazy val SeqType: TypeRef = ctx.requiredClassRef("scala.collection.Seq")
def SeqClass(implicit ctx: Context) = SeqType.symbol.asClass
diff --git a/compiler/src/dotty/tools/dotc/core/Denotations.scala b/compiler/src/dotty/tools/dotc/core/Denotations.scala
index 99c688d50..f726cd0d1 100644
--- a/compiler/src/dotty/tools/dotc/core/Denotations.scala
+++ b/compiler/src/dotty/tools/dotc/core/Denotations.scala
@@ -308,13 +308,13 @@ object Denotations {
case tp2: TypeBounds if tp2 contains tp1 => tp1
case _ => mergeConflict(tp1, tp2)
}
- case tp1 @ MethodType(names1, formals1) if isTerm =>
+ case tp1: MethodType if isTerm =>
tp2 match {
- case tp2 @ MethodType(names2, formals2) if ctx.typeComparer.matchingParams(formals1, formals2, tp1.isJava, tp2.isJava) &&
+ case tp2: MethodType if ctx.typeComparer.matchingParams(tp1.paramTypes, tp2.paramTypes, tp1.isJava, tp2.isJava) &&
tp1.isImplicit == tp2.isImplicit =>
tp1.derivedMethodType(
- mergeNames(names1, names2, nme.syntheticParamName),
- formals1,
+ mergeNames(tp1.paramNames, tp2.paramNames, nme.syntheticParamName),
+ tp1.paramTypes,
infoMeet(tp1.resultType, tp2.resultType.subst(tp2, tp1)))
case _ =>
mergeConflict(tp1, tp2)
@@ -471,14 +471,14 @@ object Denotations {
case tp2: TypeBounds if tp2 contains tp1 => tp2
case _ => mergeConflict(tp1, tp2)
}
- case tp1 @ MethodType(names1, formals1) =>
+ case tp1: MethodType =>
tp2 match {
- case tp2 @ MethodType(names2, formals2)
- if ctx.typeComparer.matchingParams(formals1, formals2, tp1.isJava, tp2.isJava) &&
+ case tp2: MethodType
+ if ctx.typeComparer.matchingParams(tp1.paramTypes, tp2.paramTypes, tp1.isJava, tp2.isJava) &&
tp1.isImplicit == tp2.isImplicit =>
tp1.derivedMethodType(
- mergeNames(names1, names2, nme.syntheticParamName),
- formals1, tp1.resultType | tp2.resultType.subst(tp2, tp1))
+ mergeNames(tp1.paramNames, tp2.paramNames, nme.syntheticParamName),
+ tp1.paramTypes, tp1.resultType | tp2.resultType.subst(tp2, tp1))
case _ =>
mergeConflict(tp1, tp2)
}
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/OrderingConstraint.scala b/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala
index 72c7a8e51..61dd5a445 100644
--- a/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala
+++ b/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala
@@ -354,14 +354,6 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
updateEntry(p1, p1Bounds).replace(p2, p1)
}
- def narrowBound(param: PolyParam, bound: Type, isUpper: Boolean)(implicit ctx: Context): This = {
- val oldBounds @ TypeBounds(lo, hi) = nonParamBounds(param)
- val newBounds =
- if (isUpper) oldBounds.derivedTypeBounds(lo, hi & bound)
- else oldBounds.derivedTypeBounds(lo | bound, hi)
- updateEntry(param, newBounds)
- }
-
// ---------- Removals ------------------------------------------------------------
/** A new constraint which is derived from this constraint by removing
diff --git a/compiler/src/dotty/tools/dotc/core/StdNames.scala b/compiler/src/dotty/tools/dotc/core/StdNames.scala
index 1e36361f8..5b7dc3d1d 100644
--- a/compiler/src/dotty/tools/dotc/core/StdNames.scala
+++ b/compiler/src/dotty/tools/dotc/core/StdNames.scala
@@ -7,7 +7,7 @@ import scala.annotation.switch
import Names._
import Symbols._
import Contexts._
-import Decorators.StringDecorator
+import Decorators.PreNamedString
import util.NameTransformer
import scala.collection.breakOut
@@ -97,6 +97,7 @@ object StdNames {
val EMPTY: N = ""
val EMPTY_PACKAGE: N = Names.EMPTY_PACKAGE.toString
val EVIDENCE_PARAM_PREFIX: N = "evidence$"
+ val DEP_PARAM_PREFIX = "<param>"
val EXCEPTION_RESULT_PREFIX: N = "exceptionResult"
val EXPAND_SEPARATOR: N = "$$"
val IMPL_CLASS_SUFFIX: N = "$class"
diff --git a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala
index 8e3b73fc0..db96463e0 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)
}
@@ -957,6 +957,10 @@ object SymDenotations {
else
companionNamed(name)(ctx.outersIterator.dropWhile(_.scope eq ctx.scope).next)
+ /** Is this symbol the same or a linked class of `sym`? */
+ final def isLinkedWith(sym: Symbol)(implicit ctx: Context): Boolean =
+ (symbol eq sym) || (linkedClass eq sym)
+
/** If this is a class, the module class of its companion object.
* If this is a module class, its companion class.
* NoSymbol otherwise.
@@ -1086,9 +1090,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 +1227,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 +1252,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/Symbols.scala b/compiler/src/dotty/tools/dotc/core/Symbols.scala
index c5e064478..33aba4d13 100644
--- a/compiler/src/dotty/tools/dotc/core/Symbols.scala
+++ b/compiler/src/dotty/tools/dotc/core/Symbols.scala
@@ -252,7 +252,7 @@ trait Symbols { this: Context =>
/** Create a class constructor symbol for given class `cls`. */
def newConstructor(cls: ClassSymbol, flags: FlagSet, paramNames: List[TermName], paramTypes: List[Type], privateWithin: Symbol = NoSymbol, coord: Coord = NoCoord) =
- newSymbol(cls, nme.CONSTRUCTOR, flags | Method, MethodType(paramNames, paramTypes)(_ => cls.typeRef), privateWithin, coord)
+ newSymbol(cls, nme.CONSTRUCTOR, flags | Method, MethodType(paramNames, paramTypes, cls.typeRef), privateWithin, coord)
/** Create an empty default constructor symbol for given class `cls`. */
def newDefaultConstructor(cls: ClassSymbol) =
@@ -496,12 +496,15 @@ object Symbols {
final def sourceFile(implicit ctx: Context): AbstractFile = {
val file = associatedFile
if (file != null && !file.path.endsWith("class")) file
- else denot.topLevelClass.getAnnotation(defn.SourceFileAnnot) match {
- case Some(sourceAnnot) => sourceAnnot.argumentConstant(0) match {
- case Some(Constant(path: String)) => AbstractFile.getFile(path)
+ else {
+ val topLevelCls = denot.topLevelClass(ctx.withPhaseNoLater(ctx.flattenPhase))
+ topLevelCls.getAnnotation(defn.SourceFileAnnot) match {
+ case Some(sourceAnnot) => sourceAnnot.argumentConstant(0) match {
+ case Some(Constant(path: String)) => AbstractFile.getFile(path)
+ case none => null
+ }
case none => null
}
- case none => null
}
}
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 fca111702..21a12dbb7 100644
--- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala
+++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala
@@ -484,11 +484,11 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
case _ =>
}
either(isSubType(tp1, tp21), isSubType(tp1, tp22)) || fourthTry(tp1, tp2)
- case tp2 @ MethodType(_, formals2) =>
+ case tp2: MethodType =>
def compareMethod = tp1 match {
- case tp1 @ MethodType(_, formals1) =>
+ case tp1: MethodType =>
(tp1.signature consistentParams tp2.signature) &&
- matchingParams(formals1, formals2, tp1.isJava, tp2.isJava) &&
+ matchingParams(tp1.paramTypes, tp2.paramTypes, tp1.isJava, tp2.isJava) &&
(tp1.isImplicit == tp2.isImplicit) &&
isSubType(tp1.resultType, tp2.resultType.subst(tp2, tp1))
case _ =>
@@ -503,7 +503,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
// as members of the same type. And it seems most logical to take
// ()T <:< => T, since everything one can do with a => T one can
// also do with a ()T by automatic () insertion.
- case tp1 @ MethodType(Nil, _) => isSubType(tp1.resultType, restpe2)
+ case tp1 @ MethodType(Nil) => isSubType(tp1.resultType, restpe2)
case _ => isSubType(tp1.widenExpr, restpe2)
}
compareExpr
@@ -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
@@ -1312,23 +1300,28 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
case tp1: RefinedType =>
tp2 match {
case tp2: RefinedType if tp1.refinedName == tp2.refinedName =>
- // Given two refinements `T1 { X = S1 }` and `T2 { X = S2 }`, if `S1 =:= S2`
- // (possibly by instantiating type parameters), rewrite to `T1 & T2 { X = S1 }`.
- // Otherwise rewrite to `T1 & T2 { X B }` where `B` is the conjunction of
- // the bounds of `X` in `T1` and `T2`.
- // The first rule above is contentious because it cuts the constraint set.
- // But without it we would replace the two aliases by
- // `T { X >: S1 | S2 <: S1 & S2 }`, which looks weird and is probably
- // not what's intended.
+ // Given two refinements `T1 { X = S1 }` and `T2 { X = S2 }` rewrite to
+ // `T1 & T2 { X B }` where `B` is the conjunction of the bounds of `X` in `T1` and `T2`.
+ //
+ // However, if `homogenizeArgs` is set, and both aliases `X = Si` are
+ // nonvariant, and `S1 =:= S2` (possibly by instantiating type parameters),
+ // rewrite instead to `T1 & T2 { X = S1 }`. This rule is contentious because
+ // it cuts the constraint set. On the other hand, without it we would replace
+ // the two aliases by `T { X >: S1 | S2 <: S1 & S2 }`, which looks weird
+ // and is probably not what's intended.
val rinfo1 = tp1.refinedInfo
val rinfo2 = tp2.refinedInfo
val parent = tp1.parent & tp2.parent
- val rinfo =
- if (rinfo1.isAlias && rinfo2.isAlias && isSameType(rinfo1, rinfo2))
- rinfo1
- else
- rinfo1 & rinfo2
- tp1.derivedRefinedType(parent, tp1.refinedName, rinfo)
+
+ def isNonvariantAlias(tp: Type) = tp match {
+ case tp: TypeAlias => tp.variance == 0
+ case _ => false
+ }
+ if (homogenizeArgs &&
+ isNonvariantAlias(rinfo1) && isNonvariantAlias(rinfo2))
+ isSameType(rinfo1, rinfo2) // establish new constraint
+
+ tp1.derivedRefinedType(parent, tp1.refinedName, rinfo1 & rinfo2)
case _ =>
NoType
}
diff --git a/compiler/src/dotty/tools/dotc/core/TypeErasure.scala b/compiler/src/dotty/tools/dotc/core/TypeErasure.scala
index fc18808a3..fe3396fcb 100644
--- a/compiler/src/dotty/tools/dotc/core/TypeErasure.scala
+++ b/compiler/src/dotty/tools/dotc/core/TypeErasure.scala
@@ -216,13 +216,13 @@ object TypeErasure {
}
/** The erased least upper bound is computed as follows
- * - if both argument are arrays of objects, an array of the lub of the element types
+ * - if both argument are arrays of objects, an array of the erased lub of the element types
* - if both arguments are arrays of same primitives, an array of this primitive
* - if one argument is array of primitives and the other is array of objects, Object
* - if one argument is an array, Object
* - otherwise a common superclass or trait S of the argument classes, with the
* following two properties:
- * S is minimal: no other common superclass or trait derives from S]
+ * S is minimal: no other common superclass or trait derives from S
* S is last : in the linearization of the first argument type `tp1`
* there are no minimal common superclasses or traits that
* come after S.
@@ -247,10 +247,14 @@ object TypeErasure {
val cls2 = tp2.classSymbol
@tailrec def loop(bcs: List[ClassSymbol], bestSoFar: ClassSymbol): ClassSymbol = bcs match {
case bc :: bcs1 =>
- if (cls2.derivesFrom(bc))
- if (!bc.is(Trait) && bc != defn.AnyClass) bc
- else loop(bcs1, if (bestSoFar.derivesFrom(bc)) bestSoFar else bc)
- else
+ if (cls2.derivesFrom(bc)) {
+ val newBest = if (bestSoFar.derivesFrom(bc)) bestSoFar else bc
+
+ if (!bc.is(Trait) && bc != defn.AnyClass)
+ newBest
+ else
+ loop(bcs1, newBest)
+ } else
loop(bcs1, bestSoFar)
case nil =>
bestSoFar
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 6ff896110..8e852a9a9 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._
@@ -216,14 +217,14 @@ object Types {
*/
def isVarArgsMethod(implicit ctx: Context): Boolean = this match {
case tp: PolyType => tp.resultType.isVarArgsMethod
- case MethodType(_, paramTypes) => paramTypes.nonEmpty && paramTypes.last.isRepeatedParam
+ case mt: MethodType => mt.paramTypes.nonEmpty && mt.paramTypes.last.isRepeatedParam
case _ => false
}
/** Is this the type of a method with a leading empty parameter list?
*/
def isNullaryMethod(implicit ctx: Context): Boolean = this match {
- case MethodType(Nil, _) => true
+ case MethodType(Nil) => true
case tp: PolyType => tp.resultType.isNullaryMethod
case _ => false
}
@@ -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) }
@@ -737,7 +732,7 @@ object Types {
*/
final def overrides(that: Type)(implicit ctx: Context) = {
def result(tp: Type): Type = tp match {
- case ExprType(_) | MethodType(Nil, _) => tp.resultType
+ case ExprType(_) | MethodType(Nil) => tp.resultType
case _ => tp
}
(this frozen_<:< that) || {
@@ -1223,8 +1218,8 @@ object Types {
* when forming the function type.
*/
def toFunctionType(dropLast: Int = 0)(implicit ctx: Context): Type = this match {
- case mt @ MethodType(_, formals) if !mt.isDependent || ctx.mode.is(Mode.AllowDependentFunctions) =>
- val formals1 = if (dropLast == 0) formals else formals dropRight dropLast
+ case mt: MethodType if !mt.isDependent || ctx.mode.is(Mode.AllowDependentFunctions) =>
+ val formals1 = if (dropLast == 0) mt.paramTypes else mt.paramTypes dropRight dropLast
defn.FunctionOf(
formals1 mapConserve (_.underlyingIfRepeated(mt.isJava)), mt.resultType, mt.isImplicit && !ctx.erasedTypes)
}
@@ -1279,10 +1274,14 @@ object Types {
def underlying(implicit ctx: Context): Type
/** The closest supertype of this type. This is the same as `underlying`,
- * except for TypeRefs where the upper bound is returned, and HKApplys,
- * where the upper bound of the constructor is re-applied to the arguments.
+ * except that
+ * - instead of a TyperBounds type it returns its upper bound, and
+ * - for HKApplys it returns the upper bound of the constructor re-applied to the arguments.
*/
- def superType(implicit ctx: Context): Type = underlying
+ def superType(implicit ctx: Context): Type = underlying match {
+ case TypeBounds(_, hi) => hi
+ case st => st
+ }
}
// Every type has to inherit one of the following four abstract type classes.,
@@ -1686,7 +1685,10 @@ object Types {
}
else newLikeThis(prefix)
}
- else newLikeThis(prefix)
+ else prefix match {
+ case _: WildcardType => WildcardType
+ case _ => newLikeThis(prefix)
+ }
/** Create a NamedType of the same kind as this type, but with a new prefix.
*/
@@ -1768,11 +1770,6 @@ object Types {
type ThisType = TypeRef
override def underlying(implicit ctx: Context): Type = info
-
- override def superType(implicit ctx: Context): Type = info match {
- case TypeBounds(_, hi) => hi
- case _ => info
- }
}
final class TermRefWithSignature(prefix: Type, name: TermName, override val sig: Signature) extends TermRef(prefix, name) {
@@ -2066,6 +2063,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 =
@@ -2312,14 +2312,16 @@ object Types {
trait MethodOrPoly extends MethodicType
- abstract case class MethodType(paramNames: List[TermName], paramTypes: List[Type])
- (resultTypeExp: MethodType => Type)
+ abstract case class MethodType(paramNames: List[TermName])(
+ paramTypesExp: MethodType => List[Type],
+ resultTypeExp: MethodType => Type)
extends CachedGroundType with BindingType with TermType with MethodOrPoly with NarrowCached { thisMethodType =>
import MethodType._
def isJava = false
def isImplicit = false
+ val paramTypes = paramTypesExp(this)
private[core] val resType = resultTypeExp(this)
assert(resType.exists)
@@ -2329,7 +2331,7 @@ object Types {
def apply(tp: Type) = tp match {
case tp @ TypeRef(pre, name) =>
tp.info match {
- case TypeAlias(alias) if depStatus(pre) == TrueDeps => apply(alias)
+ case TypeAlias(alias) if depStatus(NoDeps, pre) == TrueDeps => apply(alias)
case _ => mapOver(tp)
}
case _ =>
@@ -2341,8 +2343,9 @@ object Types {
else resType
var myDependencyStatus: DependencyStatus = Unknown
+ var myParamDependencyStatus: DependencyStatus = Unknown
- private def depStatus(tp: Type)(implicit ctx: Context): DependencyStatus = {
+ private def depStatus(initial: DependencyStatus, tp: Type)(implicit ctx: Context): DependencyStatus = {
def combine(x: DependencyStatus, y: DependencyStatus) = {
val status = (x & StatusMask) max (y & StatusMask)
val provisional = (x | y) & Provisional
@@ -2366,7 +2369,7 @@ object Types {
case _ => foldOver(status, tp)
}
}
- depStatusAcc(NoDeps, tp)
+ depStatusAcc(initial, tp)
}
/** The dependency status of this method. Some examples:
@@ -2380,17 +2383,36 @@ object Types {
private def dependencyStatus(implicit ctx: Context): DependencyStatus = {
if (myDependencyStatus != Unknown) myDependencyStatus
else {
- val result = depStatus(resType)
+ val result = depStatus(NoDeps, resType)
if ((result & Provisional) == 0) myDependencyStatus = result
(result & StatusMask).toByte
}
}
+ /** The parameter dependency status of this method. Analogous to `dependencyStatus`,
+ * but tracking dependencies in same parameter list.
+ */
+ private def paramDependencyStatus(implicit ctx: Context): DependencyStatus = {
+ if (myParamDependencyStatus != Unknown) myParamDependencyStatus
+ else {
+ val result =
+ if (paramTypes.isEmpty) NoDeps
+ else (NoDeps /: paramTypes.tail)(depStatus(_, _))
+ if ((result & Provisional) == 0) myParamDependencyStatus = result
+ (result & StatusMask).toByte
+ }
+ }
+
/** Does result type contain references to parameters of this method type,
* which cannot be eliminated by de-aliasing?
*/
def isDependent(implicit ctx: Context): Boolean = dependencyStatus == TrueDeps
+ /** Does one of the parameter types contain references to earlier parameters
+ * of this method type which cannot be eliminated by de-aliasing?
+ */
+ def isParamDependent(implicit ctx: Context): Boolean = paramDependencyStatus == TrueDeps
+
protected def computeSignature(implicit ctx: Context): Signature =
resultSignature.prepend(paramTypes, isJava)
@@ -2399,10 +2421,11 @@ object Types {
resType: Type = this.resType)(implicit ctx: Context) =
if ((paramNames eq this.paramNames) && (paramTypes eq this.paramTypes) && (resType eq this.resType)) this
else {
+ val paramTypesFn = (x: MethodType) => paramTypes.map(_.subst(this, x))
val resTypeFn = (x: MethodType) => resType.subst(this, x)
- if (isJava) JavaMethodType(paramNames, paramTypes)(resTypeFn)
- else if (isImplicit) ImplicitMethodType(paramNames, paramTypes)(resTypeFn)
- else MethodType(paramNames, paramTypes)(resTypeFn)
+ if (isJava) JavaMethodType(paramNames)(paramTypesFn, resTypeFn)
+ else if (isImplicit) ImplicitMethodType(paramNames)(paramTypesFn, resTypeFn)
+ else MethodType(paramNames)(paramTypesFn, resTypeFn)
}
def instantiate(argTypes: => List[Type])(implicit ctx: Context): Type =
@@ -2424,21 +2447,21 @@ object Types {
override def toString = s"$prefixString($paramNames, $paramTypes, $resType)"
}
- final class CachedMethodType(paramNames: List[TermName], paramTypes: List[Type])(resultTypeExp: MethodType => Type)
- extends MethodType(paramNames, paramTypes)(resultTypeExp) {
+ final class CachedMethodType(paramNames: List[TermName])(paramTypesExp: MethodType => List[Type], resultTypeExp: MethodType => Type)
+ extends MethodType(paramNames)(paramTypesExp, resultTypeExp) {
override def equals(that: Any) = super.equals(that) && that.isInstanceOf[CachedMethodType]
}
- final class JavaMethodType(paramNames: List[TermName], paramTypes: List[Type])(resultTypeExp: MethodType => Type)
- extends MethodType(paramNames, paramTypes)(resultTypeExp) {
+ final class JavaMethodType(paramNames: List[TermName])(paramTypesExp: MethodType => List[Type], resultTypeExp: MethodType => Type)
+ extends MethodType(paramNames)(paramTypesExp, resultTypeExp) {
override def isJava = true
override def equals(that: Any) = super.equals(that) && that.isInstanceOf[JavaMethodType]
override def computeHash = addDelta(super.computeHash, 1)
override protected def prefixString = "JavaMethodType"
}
- final class ImplicitMethodType(paramNames: List[TermName], paramTypes: List[Type])(resultTypeExp: MethodType => Type)
- extends MethodType(paramNames, paramTypes)(resultTypeExp) {
+ final class ImplicitMethodType(paramNames: List[TermName])(paramTypesExp: MethodType => List[Type], resultTypeExp: MethodType => Type)
+ extends MethodType(paramNames)(paramTypesExp, resultTypeExp) {
override def isImplicit = true
override def equals(that: Any) = super.equals(that) && that.isInstanceOf[ImplicitMethodType]
override def computeHash = addDelta(super.computeHash, 2)
@@ -2446,11 +2469,11 @@ object Types {
}
abstract class MethodTypeCompanion {
- def apply(paramNames: List[TermName], paramTypes: List[Type])(resultTypeExp: MethodType => Type)(implicit ctx: Context): MethodType
+ def apply(paramNames: List[TermName])(paramTypesExp: MethodType => List[Type], resultTypeExp: MethodType => Type)(implicit ctx: Context): MethodType
def apply(paramNames: List[TermName], paramTypes: List[Type], resultType: Type)(implicit ctx: Context): MethodType =
- apply(paramNames, paramTypes)(_ => resultType)
+ apply(paramNames)(_ => paramTypes, _ => resultType)
def apply(paramTypes: List[Type])(resultTypeExp: MethodType => Type)(implicit ctx: Context): MethodType =
- apply(nme.syntheticParamNames(paramTypes.length), paramTypes)(resultTypeExp)
+ apply(nme.syntheticParamNames(paramTypes.length))(_ => paramTypes, resultTypeExp)
def apply(paramTypes: List[Type], resultType: Type)(implicit ctx: Context): MethodType =
apply(nme.syntheticParamNames(paramTypes.length), paramTypes, resultType)
@@ -2473,19 +2496,31 @@ object Types {
case _: ExprType => tp
case _ => AnnotatedType(tp, Annotation(defn.InlineParamAnnot))
}
+ def integrate(tp: Type, mt: MethodType) =
+ tp.subst(params, (0 until params.length).toList.map(MethodParam(mt, _)))
def paramInfo(param: Symbol): Type = {
val paramType = translateRepeated(param.info)
if (param.is(Inline)) translateInline(paramType) else paramType
}
- def transformResult(mt: MethodType) =
- resultType.subst(params, (0 until params.length).toList map (MethodParam(mt, _)))
- apply(params map (_.name.asTermName), params map paramInfo)(transformResult _)
+ apply(params.map(_.name.asTermName))(
+ mt => params.map(param => integrate(paramInfo(param), mt)),
+ mt => integrate(resultType, mt))
+ }
+
+ def checkValid(mt: MethodType)(implicit ctx: Context): mt.type = {
+ if (Config.checkMethodTypes)
+ for ((paramType, idx) <- mt.paramTypes.zipWithIndex)
+ paramType.foreachPart {
+ case MethodParam(`mt`, j) => assert(j < idx, mt)
+ case _ =>
+ }
+ mt
}
}
object MethodType extends MethodTypeCompanion {
- def apply(paramNames: List[TermName], paramTypes: List[Type])(resultTypeExp: MethodType => Type)(implicit ctx: Context) =
- unique(new CachedMethodType(paramNames, paramTypes)(resultTypeExp))
+ def apply(paramNames: List[TermName])(paramTypesExp: MethodType => List[Type], resultTypeExp: MethodType => Type)(implicit ctx: Context): MethodType =
+ checkValid(unique(new CachedMethodType(paramNames)(paramTypesExp, resultTypeExp)))
private type DependencyStatus = Byte
private final val Unknown: DependencyStatus = 0 // not yet computed
@@ -2497,13 +2532,19 @@ object Types {
}
object JavaMethodType extends MethodTypeCompanion {
- def apply(paramNames: List[TermName], paramTypes: List[Type])(resultTypeExp: MethodType => Type)(implicit ctx: Context) =
- unique(new JavaMethodType(paramNames, paramTypes)(resultTypeExp))
+ def apply(paramNames: List[TermName])(paramTypesExp: MethodType => List[Type], resultTypeExp: MethodType => Type)(implicit ctx: Context): MethodType =
+ unique(new JavaMethodType(paramNames)(paramTypesExp, resultTypeExp))
}
object ImplicitMethodType extends MethodTypeCompanion {
- def apply(paramNames: List[TermName], paramTypes: List[Type])(resultTypeExp: MethodType => Type)(implicit ctx: Context) =
- unique(new ImplicitMethodType(paramNames, paramTypes)(resultTypeExp))
+ def apply(paramNames: List[TermName])(paramTypesExp: MethodType => List[Type], resultTypeExp: MethodType => Type)(implicit ctx: Context): MethodType =
+ checkValid(unique(new ImplicitMethodType(paramNames)(paramTypesExp, resultTypeExp)))
+ }
+
+ /** A ternary extractor for MethodType */
+ object MethodTpe {
+ def unapply(mt: MethodType)(implicit ctx: Context) =
+ Some((mt.paramNames, mt.paramTypes, mt.resultType))
}
/** A by-name parameter type of the form `=> T`, or the type of a method with no parameter list. */
@@ -2547,11 +2588,6 @@ object Types {
case _ => false
}
- /** Is this polytype a higher-kinded type lambda as opposed to a polymorphic?
- * method type? Only type lambdas get created with variances, that's how we can tell.
- */
- def isTypeLambda: Boolean = variances.nonEmpty
-
/** PolyParam references to all type parameters of this type */
lazy val paramRefs: List[PolyParam] = paramNames.indices.toList.map(PolyParam(this, _))
@@ -2928,20 +2964,8 @@ object Types {
* instantiation can be a singleton type only if the upper bound
* is also a singleton type.
*/
- def instantiate(fromBelow: Boolean)(implicit ctx: Context): Type = {
- val inst = ctx.typeComparer.instanceType(origin, fromBelow)
- if (ctx.typerState.isGlobalCommittable)
- inst match {
- case inst: PolyParam =>
- assert(inst.binder.isTypeLambda, i"bad inst $this := $inst, constr = ${ctx.typerState.constraint}")
- // If this fails, you might want to turn on Config.debugCheckConstraintsClosed
- // to help find the root of the problem.
- // Note: Parameters of type lambdas are excluded from the assertion because
- // they might arise from ill-kinded code. See #1652
- case _ =>
- }
- instantiateWith(inst)
- }
+ def instantiate(fromBelow: Boolean)(implicit ctx: Context): Type =
+ instantiateWith(ctx.typeComparer.instanceType(origin, fromBelow))
/** Unwrap to instance (if instantiated) or origin (if not), until result
* is no longer a TypeVar
@@ -3328,6 +3352,8 @@ object Types {
zeroParamClass(tp.underlying)
case tp: TypeVar =>
zeroParamClass(tp.underlying)
+ case tp: HKApply =>
+ zeroParamClass(tp.superType)
case _ =>
NoType
}
@@ -3546,6 +3572,13 @@ object Types {
def apply(tp: Type) = tp
}
+ /** A type map that approximates NoTypes by upper or lower known bounds depending on
+ * variance.
+ *
+ * if variance > 0 : approximate by upper bound
+ * variance < 0 : approximate by lower bound
+ * variance = 0 : propagate NoType to next outer level
+ */
abstract class ApproximatingTypeMap(implicit ctx: Context) extends TypeMap { thisMap =>
def approx(lo: Type = defn.NothingType, hi: Type = defn.AnyType) =
if (variance == 0) NoType
@@ -3651,9 +3684,9 @@ object Types {
this(y, hi)
}
- case tp @ MethodType(pnames, ptypes) =>
+ case tp: MethodType =>
variance = -variance
- val y = foldOver(x, ptypes)
+ val y = foldOver(x, tp.paramTypes)
variance = -variance
this(y, tp.resultType)
@@ -3856,7 +3889,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/classfile/ClassfileParser.scala b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala
index 36d478c6d..bc140c26b 100644
--- a/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala
+++ b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala
@@ -198,8 +198,8 @@ class ClassfileParser(
*/
def stripOuterParamFromConstructor() = innerClasses.get(currentClassName) match {
case Some(entry) if !isStatic(entry.jflags) =>
- val mt @ MethodType(paramnames, paramtypes) = denot.info
- denot.info = mt.derivedMethodType(paramnames.tail, paramtypes.tail, mt.resultType)
+ val mt @ MethodTpe(paramNames, paramTypes, resultType) = denot.info
+ denot.info = mt.derivedMethodType(paramNames.tail, paramTypes.tail, resultType)
case _ =>
}
@@ -207,9 +207,9 @@ class ClassfileParser(
* and make constructor type polymorphic in the type parameters of the class
*/
def normalizeConstructorInfo() = {
- val mt @ MethodType(paramnames, paramtypes) = denot.info
+ val mt @ MethodType(paramNames) = denot.info
val rt = classRoot.typeRef appliedTo (classRoot.typeParams map (_.typeRef))
- denot.info = mt.derivedMethodType(paramnames, paramtypes, rt)
+ denot.info = mt.derivedMethodType(paramNames, mt.paramTypes, rt)
addConstructorTypeParams(denot)
}
@@ -339,7 +339,7 @@ class ClassfileParser(
}
index += 1
val restype = sig2type(tparams, skiptvs)
- JavaMethodType(paramnames.toList, paramtypes.toList)(_ => restype)
+ JavaMethodType(paramnames.toList, paramtypes.toList, restype)
case 'T' =>
val n = subName(';'.==).toTypeName
index += 1
diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
index fcba957c0..a9ea49ad1 100644
--- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
+++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
@@ -278,8 +278,9 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, posUnpickle
result
case METHODtype =>
val (names, paramReader) = readNamesSkipParams
- val result = MethodType(names.map(_.toTermName), paramReader.readParamTypes[Type](end))(
- mt => registeringType(mt, readType()))
+ val result = MethodType(names.map(_.toTermName))(
+ mt => registeringType(mt, paramReader.readParamTypes[Type](end)),
+ mt => readType())
goto(end)
result
case PARAMtype =>
@@ -768,7 +769,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..688a2d007 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
@@ -55,8 +55,8 @@ object Scala2Unpickler {
* to `RepeatedParamClass` types.
*/
def arrayToRepeated(tp: Type)(implicit ctx: Context): Type = tp match {
- case tp @ MethodType(paramNames, paramTypes) =>
- val lastArg = paramTypes.last
+ case tp: MethodType =>
+ val lastArg = tp.paramTypes.last
assert(lastArg isRef defn.ArrayClass)
val elemtp0 :: Nil = lastArg.baseArgInfos(defn.ArrayClass)
val elemtp = elemtp0 match {
@@ -66,8 +66,8 @@ object Scala2Unpickler {
elemtp0
}
tp.derivedMethodType(
- paramNames,
- paramTypes.init :+ defn.RepeatedParamType.appliedTo(elemtp),
+ tp.paramNames,
+ tp.paramTypes.init :+ defn.RepeatedParamType.appliedTo(elemtp),
tp.resultType)
case tp: PolyType =>
tp.derivedPolyType(tp.paramNames, tp.paramBounds, arrayToRepeated(tp.resultType))
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 b27bff37a..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
}
@@ -1664,7 +1664,7 @@ object Parsers {
/* -------- PARAMETERS ------------------------------------------- */
/** ClsTypeParamClause::= `[' ClsTypeParam {`,' ClsTypeParam} `]'
- * ClsTypeParam ::= {Annotation} [{Modifier} type] [`+' | `-']
+ * ClsTypeParam ::= {Annotation} [`+' | `-']
* id [HkTypeParamClause] TypeParamBounds
*
* DefTypeParamClause::= `[' DefTypeParam {`,' DefTypeParam} `]'
@@ -1680,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 =
diff --git a/compiler/src/dotty/tools/dotc/parsing/Scanners.scala b/compiler/src/dotty/tools/dotc/parsing/Scanners.scala
index b75169792..847f600c0 100644
--- a/compiler/src/dotty/tools/dotc/parsing/Scanners.scala
+++ b/compiler/src/dotty/tools/dotc/parsing/Scanners.scala
@@ -6,7 +6,7 @@ import core.Names._, core.Contexts._, core.Decorators._, util.Positions._
import core.StdNames._, core.Comments._
import util.SourceFile
import java.lang.Character.isDigit
-import scala.reflect.internal.Chars._
+import util.Chars._
import Tokens._
import scala.annotation.{ switch, tailrec }
import scala.collection.mutable
diff --git a/compiler/src/dotty/tools/dotc/parsing/SymbolicXMLBuilder.scala b/compiler/src/dotty/tools/dotc/parsing/SymbolicXMLBuilder.scala
index 09d1b20b1..c99826488 100644
--- a/compiler/src/dotty/tools/dotc/parsing/SymbolicXMLBuilder.scala
+++ b/compiler/src/dotty/tools/dotc/parsing/SymbolicXMLBuilder.scala
@@ -5,12 +5,12 @@ package parsing
import scala.collection.mutable
import scala.xml.{ EntityRef, Text }
import core._
+import Decorators._
import Flags.Mutable
import Names._, StdNames._, ast.Trees._, ast.{tpd, untpd}
import Symbols._, Contexts._
import util.Positions._
import Parsers.Parser
-import scala.reflect.internal.util.StringOps.splitWhere
import scala.language.implicitConversions
/** This class builds instance of `Tree` that represent XML.
@@ -171,7 +171,7 @@ class SymbolicXMLBuilder(parser: Parser, preserveWS: Boolean)(implicit ctx: Cont
}
/** Returns (Some(prefix) | None, rest) based on position of ':' */
- def splitPrefix(name: String): (Option[String], String) = splitWhere(name, _ == ':', true) match {
+ def splitPrefix(name: String): (Option[String], String) = name.splitWhere(_ == ':', doDropIndex = true) match {
case Some((pre, rest)) => (Some(pre), rest)
case _ => (None, name)
}
diff --git a/compiler/src/dotty/tools/dotc/parsing/Utility.scala b/compiler/src/dotty/tools/dotc/parsing/Utility.scala
index f522492f8..8af594d68 100644
--- a/compiler/src/dotty/tools/dotc/parsing/Utility.scala
+++ b/compiler/src/dotty/tools/dotc/parsing/Utility.scala
@@ -1,4 +1,5 @@
-package dotty.tools.dotc.parsing
+package dotty.tools.dotc
+package parsing
import scala.collection.mutable
@@ -10,7 +11,7 @@ import scala.collection.mutable
* @author Burak Emir
*/
object Utility {
- import scala.reflect.internal.Chars.SU
+ import util.Chars.SU
private val unescMap = Map(
"lt" -> '<',
diff --git a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala
index 0d1068b8c..67d44daa1 100644
--- a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala
+++ b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala
@@ -4,6 +4,7 @@ package printing
import core._
import Texts._, Types._, Flags._, Names._, Symbols._, NameOps._, Constants._, Denotations._
import Contexts.Context, Scopes.Scope, Denotations.Denotation, Annotations.Annotation
+import TypeApplications.AppliedType
import StdNames.{nme, tpnme}
import ast.Trees._, ast._
import typer.Implicits._
@@ -119,10 +120,11 @@ class PlainPrinter(_ctx: Context) extends Printer {
}
/** The longest sequence of refinement types, starting at given type
- * and following parents.
+ * and following parents, but stopping at applied types.
*/
private def refinementChain(tp: Type): List[Type] =
tp :: (tp match {
+ case AppliedType(_, _) => Nil
case tp: RefinedType => refinementChain(tp.parent.stripTypeVar)
case _ => Nil
})
@@ -481,7 +483,7 @@ class PlainPrinter(_ctx: Context) extends Printer {
else
Text()
- nodeName ~ "(" ~ elems ~ tpSuffix ~ ")" ~ node.pos.toString
+ nodeName ~ "(" ~ elems ~ tpSuffix ~ ")" ~ (node.pos.toString provided ctx.settings.Yprintpos.value)
case _ =>
tree.fallbackToText(this)
}
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 bbd93eb30..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,
@@ -52,6 +51,10 @@ public enum ErrorMessageID {
MixedLeftAndRightAssociativeOpsID,
CantInstantiateAbstractClassOrTraitID,
AnnotatedPrimaryConstructorRequiresModifierOrThisID,
+ OverloadedOrRecursiveMethodNeedsResultTypeID,
+ RecursiveValueNeedsResultTypeID,
+ CyclicReferenceInvolvingID,
+ CyclicReferenceInvolvingImplicitID,
;
public int errorNumber() {
diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala
index e367e9ab2..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"
@@ -1138,7 +1126,7 @@ object messages {
|
|You may want to create an anonymous class extending ${cls.name} with
| ${s"class ${cls.name} { }"}
- |
+ |
|or add a companion object with
| ${s"object ${cls.name} extends ${cls.name}"}
|
@@ -1147,7 +1135,7 @@ object messages {
}
case class AnnotatedPrimaryConstructorRequiresModifierOrThis(cls: Name)(implicit ctx: Context)
- extends Message(AnnotatedPrimaryConstructorRequiresModifierOrThisID) {
+ extends Message(AnnotatedPrimaryConstructorRequiresModifierOrThisID) {
val kind = "Syntax"
val msg = hl"""${"private"}, ${"protected"}, or ${"this"} expected for annotated primary constructor"""
val explanation =
@@ -1160,4 +1148,48 @@ object messages {
| ^^^^
|""".stripMargin
}
+
+ case class OverloadedOrRecursiveMethodNeedsResultType(tree: Names.TermName)(implicit ctx: Context)
+ extends Message(OverloadedOrRecursiveMethodNeedsResultTypeID) {
+ val kind = "Syntax"
+ val msg = hl"""overloaded or recursive method ${tree} needs return type"""
+ val explanation =
+ hl"""Case 1: ${tree} is overloaded
+ |If there are multiple methods named `${tree.name}` and at least one definition of
+ |it calls another, you need to specify the calling method's return type.
+ |
+ |Case 2: ${tree} is recursive
+ |If `${tree.name}` calls itself on any path, you need to specify its return type.
+ |""".stripMargin
+ }
+
+ case class RecursiveValueNeedsResultType(tree: Names.TermName)(implicit ctx: Context)
+ extends Message(RecursiveValueNeedsResultTypeID) {
+ val kind = "Syntax"
+ val msg = hl"""recursive value ${tree.name} needs type"""
+ val explanation =
+ hl"""The definition of `${tree.name}` is recursive and you need to specify its type.
+ |""".stripMargin
+ }
+
+ case class CyclicReferenceInvolving(denot: SymDenotation)(implicit ctx: Context)
+ extends Message(CyclicReferenceInvolvingID) {
+ val kind = "Syntax"
+ val msg = hl"""cyclic reference involving $denot"""
+ val explanation =
+ hl"""|$denot is declared as part of a cycle which makes it impossible for the
+ |compiler to decide upon ${denot.name}'s type.
+ |""".stripMargin
+ }
+
+ case class CyclicReferenceInvolvingImplicit(cycleSym: Symbol)(implicit ctx: Context)
+ extends Message(CyclicReferenceInvolvingImplicitID) {
+ val kind = "Syntax"
+ val msg = hl"""cyclic reference involving implicit $cycleSym"""
+ val explanation =
+ hl"""|This happens when the right hand-side of $cycleSym's definition involves an implicit search.
+ |To avoid this error, give `${cycleSym.name}` an explicit type.
+ |""".stripMargin
+ }
+
}
diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala
index 7f44af486..43202ef87 100644
--- a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala
+++ b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala
@@ -284,7 +284,7 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder
case pt: PolyType =>
assert(start == 0)
paramLists(pt.resultType)
- case mt @ MethodType(pnames, ptypes) =>
+ case mt @ MethodTpe(pnames, ptypes, restpe) =>
// TODO: We shouldn't have to work so hard to find the default parameters
// of a method, Dotty should expose a convenience method for that, see #1143
val defaults =
@@ -300,7 +300,7 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder
val params = (pnames, ptypes, defaults).zipped.map((pname, ptype, isDefault) =>
new api.MethodParameter(pname.toString, apiType(ptype),
isDefault, api.ParameterModifier.Plain))
- new api.ParameterList(params.toArray, mt.isImplicit) :: paramLists(mt.resultType, params.length)
+ new api.ParameterList(params.toArray, mt.isImplicit) :: paramLists(restpe, params.length)
case _ =>
Nil
}
@@ -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/CollectEntryPoints.scala b/compiler/src/dotty/tools/dotc/transform/CollectEntryPoints.scala
index 331fce46a..9f1e42e31 100644
--- a/compiler/src/dotty/tools/dotc/transform/CollectEntryPoints.scala
+++ b/compiler/src/dotty/tools/dotc/transform/CollectEntryPoints.scala
@@ -64,7 +64,7 @@ class CollectEntryPoints extends MiniPhaseTransform {
val hasApproximate = possibles exists {
m =>
m.info match {
- case MethodType(_, p :: Nil) =>
+ case MethodTpe(_, p :: Nil, _) =>
p.typeSymbol == defn.ArrayClass
case _ => false
}
@@ -87,8 +87,8 @@ class CollectEntryPoints extends MiniPhaseTransform {
m.symbol.info match {
case t: PolyType =>
fail("main methods cannot be generic.")
- case t@MethodType(paramNames, paramTypes) =>
- if (t.resultType :: paramTypes exists (_.typeSymbol.isAbstractType))
+ case t: MethodType =>
+ if (t.resultType :: t.paramTypes exists (_.typeSymbol.isAbstractType))
fail("main methods cannot refer to type parameters or abstract types.", m.symbol.pos)
else
javaPlatform.isJavaMainMethod(m.symbol) || fail("main method must have exact signature (Array[String])Unit", m.symbol.pos)
diff --git a/compiler/src/dotty/tools/dotc/transform/ElimByName.scala b/compiler/src/dotty/tools/dotc/transform/ElimByName.scala
index 0e187fc2e..59da78590 100644
--- a/compiler/src/dotty/tools/dotc/transform/ElimByName.scala
+++ b/compiler/src/dotty/tools/dotc/transform/ElimByName.scala
@@ -92,8 +92,8 @@ class ElimByName extends MiniPhaseTransform with InfoTransformer { thisTransform
arg
}
- val MethodType(_, formals) = tree.fun.tpe.widen
- val args1 = tree.args.zipWithConserve(formals)(transformArg)
+ val mt @ MethodType(_) = tree.fun.tpe.widen
+ val args1 = tree.args.zipWithConserve(mt.paramTypes)(transformArg)
cpy.Apply(tree)(tree.fun, args1)
}
diff --git a/compiler/src/dotty/tools/dotc/transform/ElimRepeated.scala b/compiler/src/dotty/tools/dotc/transform/ElimRepeated.scala
index 258b7f234..ae3259509 100644
--- a/compiler/src/dotty/tools/dotc/transform/ElimRepeated.scala
+++ b/compiler/src/dotty/tools/dotc/transform/ElimRepeated.scala
@@ -32,11 +32,24 @@ class ElimRepeated extends MiniPhaseTransform with InfoTransformer with Annotati
def transformInfo(tp: Type, sym: Symbol)(implicit ctx: Context): Type =
elimRepeated(tp)
+
+ override def transform(ref: SingleDenotation)(implicit ctx: Context): SingleDenotation =
+ super.transform(ref) match {
+ case ref1: SymDenotation if (ref1 ne ref) && overridesJava(ref1.symbol) =>
+ // This method won't override the corresponding Java method at the end of this phase,
+ // only the bridge added by `addVarArgsBridge` will.
+ ref1.copySymDenotation(initFlags = ref1.flags &~ Override)
+ case ref1 =>
+ ref1
+ }
+
override def mayChange(sym: Symbol)(implicit ctx: Context): Boolean = sym is Method
+ private def overridesJava(sym: Symbol)(implicit ctx: Context) = sym.allOverriddenSymbols.exists(_ is JavaDefined)
+
private def elimRepeated(tp: Type)(implicit ctx: Context): Type = tp.stripTypeVar match {
- case tp @ MethodType(paramNames, paramTypes) =>
- val resultType1 = elimRepeated(tp.resultType)
+ case tp @ MethodTpe(paramNames, paramTypes, resultType) =>
+ val resultType1 = elimRepeated(resultType)
val paramTypes1 =
if (paramTypes.nonEmpty && paramTypes.last.isRepeatedParam) {
val last = paramTypes.last.underlyingIfRepeated(tp.isJava)
@@ -93,10 +106,9 @@ class ElimRepeated extends MiniPhaseTransform with InfoTransformer with Annotati
*/
override def transformDefDef(tree: DefDef)(implicit ctx: Context, info: TransformerInfo): Tree = {
assert(ctx.phase == thisTransformer)
- def overridesJava = tree.symbol.allOverriddenSymbols.exists(_ is JavaDefined)
- if (tree.symbol.info.isVarArgsMethod && overridesJava)
- addVarArgsBridge(tree)(ctx.withPhase(thisTransformer.next))
- else
+ if (tree.symbol.info.isVarArgsMethod && overridesJava(tree.symbol))
+ addVarArgsBridge(tree)
+ else
tree
}
@@ -120,6 +132,7 @@ class ElimRepeated extends MiniPhaseTransform with InfoTransformer with Annotati
.appliedToArgs(vrefs :+ TreeGen.wrapArray(varArgRef, elemtp))
.appliedToArgss(vrefss1)
})
+
Thicket(ddef, bridgeDef)
}
diff --git a/compiler/src/dotty/tools/dotc/transform/Erasure.scala b/compiler/src/dotty/tools/dotc/transform/Erasure.scala
index 3857b405f..f9c7a8e1e 100644
--- a/compiler/src/dotty/tools/dotc/transform/Erasure.scala
+++ b/compiler/src/dotty/tools/dotc/transform/Erasure.scala
@@ -40,8 +40,8 @@ class Erasure extends Phase with DenotTransformer { thisTransformer =>
def isCompacted(sym: Symbol) =
sym.isAnonymousFunction && {
sym.info(ctx.withPhase(ctx.phase.next)) match {
- case MethodType(nme.ALLARGS :: Nil, _) => true
- case _ => false
+ case MethodType(nme.ALLARGS :: Nil) => true
+ case _ => false
}
}
@@ -269,7 +269,7 @@ object Erasure extends TypeTestsCasts{
def adaptToType(tree: Tree, pt: Type)(implicit ctx: Context): Tree =
if (pt.isInstanceOf[FunProto]) tree
else tree.tpe.widen match {
- case MethodType(Nil, _) if tree.isTerm =>
+ case MethodType(Nil) if tree.isTerm =>
adaptToType(tree.appliedToNone, pt)
case tpw =>
if (pt.isInstanceOf[ProtoType] || tree.tpe <:< pt)
@@ -697,9 +697,10 @@ object Erasure extends TypeTestsCasts{
val rhs = paramss.foldLeft(sel)((fun, vparams) =>
fun.tpe.widen match {
- case MethodType(names, types) => Apply(fun, (vparams, types).zipped.map(adapt(_, _, untpd.EmptyTree)))
- case a => error(s"can not resolve apply type $a")
-
+ case mt: MethodType =>
+ Apply(fun, (vparams, mt.paramTypes).zipped.map(adapt(_, _, untpd.EmptyTree)))
+ case a =>
+ error(s"can not resolve apply type $a")
})
adapt(rhs, resultType)
})
diff --git a/compiler/src/dotty/tools/dotc/transform/ExpandSAMs.scala b/compiler/src/dotty/tools/dotc/transform/ExpandSAMs.scala
index 91399f91a..7b15b7e54 100644
--- a/compiler/src/dotty/tools/dotc/transform/ExpandSAMs.scala
+++ b/compiler/src/dotty/tools/dotc/transform/ExpandSAMs.scala
@@ -53,7 +53,7 @@ class ExpandSAMs extends MiniPhaseTransform { thisTransformer =>
val applyRhs: Tree = applyDef.rhs
val applyFn = applyDef.symbol.asTerm
- val MethodType(paramNames, paramTypes) = applyFn.info
+ val MethodTpe(paramNames, paramTypes, _) = applyFn.info
val isDefinedAtFn = applyFn.copy(
name = nme.isDefinedAt,
flags = Synthetic | Method,
diff --git a/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala b/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala
index 44308012e..f17808e62 100644
--- a/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala
+++ b/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala
@@ -330,9 +330,9 @@ object ExplicitOuter {
/** If `cls` has an outer parameter add one to the method type `tp`. */
def addParam(cls: ClassSymbol, tp: Type): Type =
if (hasOuterParam(cls)) {
- val mt @ MethodType(pnames, ptypes) = tp
+ val mt @ MethodTpe(pnames, ptypes, restpe) = tp
mt.derivedMethodType(
- nme.OUTER :: pnames, cls.owner.enclosingClass.typeRef :: ptypes, mt.resultType)
+ nme.OUTER :: pnames, cls.owner.enclosingClass.typeRef :: ptypes, restpe)
} else tp
/** If function in an apply node is a constructor that needs to be passed an
@@ -391,7 +391,7 @@ object ExplicitOuter {
/** The outer parameter definition of a constructor if it needs one */
def paramDefs(constr: Symbol): List[ValDef] =
if (constr.isConstructor && hasOuterParam(constr.owner.asClass)) {
- val MethodType(outerName :: _, outerType :: _) = constr.info
+ val MethodTpe(outerName :: _, outerType :: _, _) = constr.info
val outerSym = ctx.newSymbol(constr, outerName, Param, outerType)
ValDef(outerSym) :: Nil
}
diff --git a/compiler/src/dotty/tools/dotc/transform/FirstTransform.scala b/compiler/src/dotty/tools/dotc/transform/FirstTransform.scala
index 597146514..8328e43de 100644
--- a/compiler/src/dotty/tools/dotc/transform/FirstTransform.scala
+++ b/compiler/src/dotty/tools/dotc/transform/FirstTransform.scala
@@ -29,8 +29,11 @@ import StdNames._
* - eliminates some kinds of trees: Imports, NamedArgs
* - stubs out native methods
* - eliminates self tree in Template and self symbol in ClassInfo
- * - collapsess all type trees to trees of class TypeTree
+ * - collapses all type trees to trees of class TypeTree
* - converts idempotent expressions with constant types
+ * - drops branches of ifs using the rules
+ * if (true) A else B --> A
+ * if (false) A else B --> B
*/
class FirstTransform extends MiniPhaseTransform with InfoTransformer with AnnotationTransformer { thisTransformer =>
import ast.tpd._
@@ -148,7 +151,7 @@ class FirstTransform extends MiniPhaseTransform with InfoTransformer with Annota
override def transformTemplate(impl: Template)(implicit ctx: Context, info: TransformerInfo): Tree = {
cpy.Template(impl)(self = EmptyValDef)
}
-
+
override def transformDefDef(ddef: DefDef)(implicit ctx: Context, info: TransformerInfo) = {
if (ddef.symbol.hasAnnotation(defn.NativeAnnot)) {
ddef.symbol.resetFlag(Deferred)
@@ -168,13 +171,13 @@ class FirstTransform extends MiniPhaseTransform with InfoTransformer with Annota
}
override def transformIdent(tree: Ident)(implicit ctx: Context, info: TransformerInfo) =
- if (tree.isType) TypeTree(tree.tpe).withPos(tree.pos)
+ if (tree.isType) TypeTree(tree.tpe).withPos(tree.pos)
else constToLiteral(tree)
override def transformSelect(tree: Select)(implicit ctx: Context, info: TransformerInfo) =
- if (tree.isType) TypeTree(tree.tpe).withPos(tree.pos)
+ if (tree.isType) TypeTree(tree.tpe).withPos(tree.pos)
else constToLiteral(tree)
-
+
override def transformTypeApply(tree: TypeApply)(implicit ctx: Context, info: TransformerInfo) =
constToLiteral(tree)
@@ -183,10 +186,16 @@ class FirstTransform extends MiniPhaseTransform with InfoTransformer with Annota
override def transformTyped(tree: Typed)(implicit ctx: Context, info: TransformerInfo) =
constToLiteral(tree)
-
+
override def transformBlock(tree: Block)(implicit ctx: Context, info: TransformerInfo) =
constToLiteral(tree)
+ override def transformIf(tree: If)(implicit ctx: Context, info: TransformerInfo) =
+ tree.cond match {
+ case Literal(Constant(c: Boolean)) => if (c) tree.thenp else tree.elsep
+ case _ => tree
+ }
+
// invariants: all modules have companion objects
// all types are TypeTrees
// all this types are explicit
diff --git a/compiler/src/dotty/tools/dotc/transform/FullParameterization.scala b/compiler/src/dotty/tools/dotc/transform/FullParameterization.scala
index 9e43fc999..0cb453b4c 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
@@ -107,8 +105,9 @@ trait FullParameterization {
def resultType(mapClassParams: Type => Type) = {
val thisParamType = mapClassParams(clazz.classInfo.selfType)
val firstArgType = if (liftThisType) thisParamType & clazz.thisType else thisParamType
- MethodType(nme.SELF :: Nil, firstArgType :: Nil)(mt =>
- mapClassParams(origResult).substThisUnlessStatic(clazz, MethodParam(mt, 0)))
+ MethodType(nme.SELF :: Nil)(
+ mt => firstArgType :: Nil,
+ mt => mapClassParams(origResult).substThisUnlessStatic(clazz, MethodParam(mt, 0)))
}
/** Replace class type parameters by the added type parameters of the polytype `pt` */
@@ -234,8 +233,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)
})
@@ -254,10 +253,10 @@ object FullParameterization {
def memberSignature(info: Type)(implicit ctx: Context): Signature = info match {
case info: PolyType =>
memberSignature(info.resultType)
- case info @ MethodType(nme.SELF :: Nil, _) =>
- info.resultType.ensureMethodic.signature
- case info @ MethodType(nme.SELF :: otherNames, thisType :: otherTypes) =>
- info.derivedMethodType(otherNames, otherTypes, info.resultType).signature
+ case MethodTpe(nme.SELF :: Nil, _, restpe) =>
+ restpe.ensureMethodic.signature
+ case info @ MethodTpe(nme.SELF :: otherNames, thisType :: otherTypes, restpe) =>
+ info.derivedMethodType(otherNames, otherTypes, restpe).signature
case _ =>
Signature.NotAMethod
}
diff --git a/compiler/src/dotty/tools/dotc/transform/LambdaLift.scala b/compiler/src/dotty/tools/dotc/transform/LambdaLift.scala
index b603a53dc..7578b57f1 100644
--- a/compiler/src/dotty/tools/dotc/transform/LambdaLift.scala
+++ b/compiler/src/dotty/tools/dotc/transform/LambdaLift.scala
@@ -352,12 +352,12 @@ class LambdaLift extends MiniPhase with IdentityDenotTransformer { thisTransform
}
private def liftedInfo(local: Symbol)(implicit ctx: Context): Type = local.info match {
- case mt @ MethodType(pnames, ptypes) =>
+ case MethodTpe(pnames, ptypes, restpe) =>
val ps = proxies(local)
MethodType(
ps.map(_.name.asTermName) ++ pnames,
ps.map(_.info) ++ ptypes,
- mt.resultType)
+ restpe)
case info => info
}
diff --git a/compiler/src/dotty/tools/dotc/transform/LazyVals.scala b/compiler/src/dotty/tools/dotc/transform/LazyVals.scala
index a6ac71286..2035fb04b 100644
--- a/compiler/src/dotty/tools/dotc/transform/LazyVals.scala
+++ b/compiler/src/dotty/tools/dotc/transform/LazyVals.scala
@@ -139,7 +139,7 @@ class LazyVals extends MiniPhaseTransform with IdentityDenotTransformer {
val holderSymbol = ctx.newSymbol(x.symbol.owner, holderName, containerFlags, holderImpl.typeRef, coord = x.pos)
val initSymbol = ctx.newSymbol(x.symbol.owner, initName, initFlags, MethodType(Nil, tpe), coord = x.pos)
- val result = ref(holderSymbol).select(lazyNme.value)
+ val result = ref(holderSymbol).select(lazyNme.value).withPos(x.pos)
val flag = ref(holderSymbol).select(lazyNme.initialized)
val initer = valueInitter.changeOwnerAfter(x.symbol, initSymbol, this)
val initBody =
diff --git a/compiler/src/dotty/tools/dotc/transform/ParamForwarding.scala b/compiler/src/dotty/tools/dotc/transform/ParamForwarding.scala
index a72e10681..859ac8b06 100644
--- a/compiler/src/dotty/tools/dotc/transform/ParamForwarding.scala
+++ b/compiler/src/dotty/tools/dotc/transform/ParamForwarding.scala
@@ -27,7 +27,7 @@ class ParamForwarding(thisTransformer: DenotTransformer) {
val (superArgs, superParamNames) = impl.parents match {
case superCall @ Apply(fn, args) :: _ =>
fn.tpe.widen match {
- case MethodType(paramNames, _) => (args, paramNames)
+ case MethodType(paramNames) => (args, paramNames)
case _ => (Nil, Nil)
}
case _ => (Nil, Nil)
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/transform/TreeChecker.scala b/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala
index 7a4af647f..51e2469b2 100644
--- a/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala
+++ b/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala
@@ -446,7 +446,7 @@ class TreeChecker extends Phase with SymTransformer {
super.typedStats(trees, exprOwner)
}
- override def ensureNoLocalRefs(tree: Tree, pt: Type, localSyms: => List[Symbol], forcedDefined: Boolean = false)(implicit ctx: Context): Tree =
+ override def ensureNoLocalRefs(tree: Tree, pt: Type, localSyms: => List[Symbol])(implicit ctx: Context): Tree =
tree
override def adapt(tree: Tree, pt: Type, original: untpd.Tree = untpd.EmptyTree)(implicit ctx: Context) = {
diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala
index e9df12b42..5dcf16b62 100644
--- a/compiler/src/dotty/tools/dotc/typer/Applications.scala
+++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala
@@ -178,6 +178,8 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
*/
protected def normalizedFun: Tree
+ protected def typeOfArg(arg: Arg): Type
+
/** If constructing trees, pull out all parts of the function
* which are not idempotent into separate prefix definitions
*/
@@ -213,16 +215,15 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
protected def init() = methType match {
case methType: MethodType =>
// apply the result type constraint, unless method type is dependent
- if (!methType.isDependent) {
- val savedConstraint = ctx.typerState.constraint
- if (!constrainResult(methType.resultType, resultType))
- if (ctx.typerState.isCommittable)
- // defer the problem until after the application;
- // it might be healed by an implicit conversion
- assert(ctx.typerState.constraint eq savedConstraint)
- else
- fail(err.typeMismatchMsg(methType.resultType, resultType))
- }
+ val resultApprox = resultTypeApprox(methType)
+ val savedConstraint = ctx.typerState.constraint
+ if (!constrainResult(resultApprox, resultType))
+ if (ctx.typerState.isCommittable)
+ // defer the problem until after the application;
+ // it might be healed by an implicit conversion
+ assert(ctx.typerState.constraint eq savedConstraint)
+ else
+ fail(err.typeMismatchMsg(methType.resultType, resultType))
// match all arguments with corresponding formal parameters
matchArgs(orderedArgs, methType.paramTypes, 0)
case _ =>
@@ -381,8 +382,16 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
if (success) formals match {
case formal :: formals1 =>
- def addTyped(arg: Arg, formal: Type) =
+ /** Add result of typing argument `arg` against parameter type `formal`.
+ * @return A type transformation to apply to all arguments following this one.
+ */
+ def addTyped(arg: Arg, formal: Type): Type => Type = {
addArg(typedArg(arg, formal), formal)
+ if (methodType.isParamDependent)
+ _.substParam(MethodParam(methodType, n), typeOfArg(arg))
+ else
+ identity
+ }
def missingArg(n: Int): Unit = {
val pname = methodType.paramNames(n)
@@ -396,8 +405,10 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
val getter = findDefaultGetter(n + numArgs(normalizedFun))
if (getter.isEmpty) missingArg(n)
else {
- addTyped(treeToArg(spliceMeth(getter withPos normalizedFun.pos, normalizedFun)), formal)
- matchArgs(args1, formals1, n + 1)
+ val substParam = addTyped(
+ treeToArg(spliceMeth(getter withPos normalizedFun.pos, normalizedFun)),
+ formal)
+ matchArgs(args1, formals1.mapconserve(substParam), n + 1)
}
}
@@ -421,8 +432,8 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
case EmptyTree :: args1 =>
tryDefault(n, args1)
case arg :: args1 =>
- addTyped(arg, formal)
- matchArgs(args1, formals1, n + 1)
+ val substParam = addTyped(arg, formal)
+ matchArgs(args1, formals1.mapconserve(substParam), n + 1)
case nil =>
tryDefault(n, args)
}
@@ -478,6 +489,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
def argType(arg: Tree, formal: Type): Type = normalize(arg.tpe, formal)
def treeToArg(arg: Tree): Tree = arg
def isVarArg(arg: Tree): Boolean = tpd.isWildcardStarArg(arg)
+ def typeOfArg(arg: Tree): Type = arg.tpe
def harmonizeArgs(args: List[Tree]) = harmonize(args)
}
@@ -495,6 +507,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
def argType(arg: Type, formal: Type): Type = arg
def treeToArg(arg: Tree): Type = arg.tpe
def isVarArg(arg: Type): Boolean = arg.isRepeatedParam
+ def typeOfArg(arg: Type): Type = arg
def harmonizeArgs(args: List[Type]) = harmonizeTypes(args)
}
@@ -593,6 +606,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
extends TypedApply(app, fun, methRef, proto.args, resultType) {
def typedArg(arg: untpd.Tree, formal: Type): TypedArg = proto.typedArg(arg, formal.widenExpr)
def treeToArg(arg: Tree): untpd.Tree = untpd.TypedSplice(arg)
+ def typeOfArg(arg: untpd.Tree) = proto.typeOfArg(arg)
}
/** Subclass of Application for type checking an Apply node with typed arguments. */
@@ -604,6 +618,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
// not match the abstract method in Application and an abstract class error results.
def typedArg(arg: tpd.Tree, formal: Type): TypedArg = arg
def treeToArg(arg: Tree): Tree = arg
+ def typeOfArg(arg: Tree) = arg.tpe
}
/** If `app` is a `this(...)` constructor call, the this-call argument context,
@@ -1100,10 +1115,8 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
/** Drop any implicit parameter section */
def stripImplicit(tp: Type): Type = tp match {
- case mt: ImplicitMethodType if !mt.isDependent =>
- mt.resultType
- // todo: make sure implicit method types are not dependent?
- // but check test case in /tests/pos/depmet_implicit_chaining_zw.scala
+ case mt: ImplicitMethodType =>
+ resultTypeApprox(mt)
case pt: PolyType =>
pt.derivedPolyType(pt.paramNames, pt.paramBounds, stripImplicit(pt.resultType))
case _ =>
@@ -1266,7 +1279,8 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
def sizeFits(alt: TermRef, tp: Type): Boolean = tp match {
case tp: PolyType => sizeFits(alt, tp.resultType)
- case MethodType(_, ptypes) =>
+ case tp: MethodType =>
+ val ptypes = tp.paramTypes
val numParams = ptypes.length
def isVarArgs = ptypes.nonEmpty && ptypes.last.isRepeatedParam
def hasDefault = alt.symbol.hasDefaultParams
@@ -1384,7 +1398,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..b43391592 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)
@@ -357,7 +357,7 @@ object Checking {
*/
def checkNoPrivateLeaks(sym: Symbol, pos: Position)(implicit ctx: Context): Type = {
class NotPrivate extends TypeMap {
- var errors: List[String] = Nil
+ var errors: List[() => String] = Nil
def accessBoundary(sym: Symbol): Symbol =
if (sym.is(Private) || !sym.owner.isClass) sym.owner
@@ -384,7 +384,7 @@ object Checking {
var tp1 =
if (isLeaked(tp.symbol)) {
errors =
- em"non-private $sym refers to private ${tp.symbol}\n in its type signature ${sym.info}" :: errors
+ (() => em"non-private $sym refers to private ${tp.symbol}\n in its type signature ${sym.info}") :: errors
tp
}
else mapOver(tp)
@@ -408,7 +408,7 @@ object Checking {
}
val notPrivate = new NotPrivate
val info = notPrivate(sym.info)
- notPrivate.errors.foreach(ctx.errorOrMigrationWarning(_, pos))
+ notPrivate.errors.foreach(error => ctx.errorOrMigrationWarning(error(), pos))
info
}
@@ -441,7 +441,6 @@ object Checking {
case List(param) =>
if (param.is(Mutable))
ctx.error("value class parameter must not be a var", param.pos)
-
case _ =>
ctx.error("value class needs to have exactly one val parameter", clazz.pos)
}
@@ -625,6 +624,24 @@ trait Checking {
case _ =>
}
}
+
+ /** Check that method parameter types do not reference their own parameter
+ * or later parameters in the same parameter section.
+ */
+ def checkNoForwardDependencies(vparams: List[ValDef])(implicit ctx: Context): Unit = vparams match {
+ case vparam :: vparams1 =>
+ val check = new TreeTraverser {
+ def traverse(tree: Tree)(implicit ctx: Context) = tree match {
+ case id: Ident if vparams.exists(_.symbol == id.symbol) =>
+ ctx.error("illegal forward reference to method parameter", id.pos)
+ case _ =>
+ traverseChildren(tree)
+ }
+ }
+ check.traverse(vparam.tpt)
+ checkNoForwardDependencies(vparams1)
+ case Nil =>
+ }
}
trait NoChecking extends Checking {
@@ -642,4 +659,5 @@ trait NoChecking extends Checking {
override def checkNotSingleton(tpt: Tree, where: String)(implicit ctx: Context): Tree = tpt
override def checkDerivedValueClass(clazz: Symbol, stats: List[Tree])(implicit ctx: Context) = ()
override def checkTraitInheritance(parentSym: Symbol, cls: ClassSymbol, pos: Position)(implicit ctx: Context) = ()
+ override def checkNoForwardDependencies(vparams: List[ValDef])(implicit ctx: Context): Unit = ()
}
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/EtaExpansion.scala b/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala
index e7e7ece78..57c1808c9 100644
--- a/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala
+++ b/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala
@@ -59,8 +59,8 @@ object EtaExpansion {
*/
def liftArgs(defs: mutable.ListBuffer[Tree], methRef: Type, args: List[Tree])(implicit ctx: Context) =
methRef.widen match {
- case MethodType(paramNames, paramTypes) =>
- (args, paramNames, paramTypes).zipped map { (arg, name, tp) =>
+ case mt: MethodType =>
+ (args, mt.paramNames, mt.paramTypes).zipped map { (arg, name, tp) =>
if (tp.isInstanceOf[ExprType]) arg
else liftArg(defs, arg, if (name contains '$') "" else name.toString + "$")
}
diff --git a/compiler/src/dotty/tools/dotc/typer/Implicits.scala b/compiler/src/dotty/tools/dotc/typer/Implicits.scala
index d5afae90c..681045cc4 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,9 +514,15 @@ 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)
+ else {
+ def adjust(to: Type) = to.stripTypeVar.widenExpr match {
+ case SelectionProto(name, memberProto, compat, true) =>
+ SelectionProto(name, memberProto, compat, privateOK = false)
+ case tp => tp
+ }
+ try inferImplicit(adjust(to), from, from.pos)
catch {
case ex: AssertionError =>
implicits.println(s"view $from ==> $to")
@@ -506,6 +530,7 @@ trait Implicits { self: Typer =>
implicits.println(TypeComparer.explained(implicit ctx => from.tpe <:< to))
throw ex
}
+ }
}
/** Find an implicit argument for parameter `formal`.
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/ProtoTypes.scala b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala
index d666b563e..f7dd725c8 100644
--- a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala
+++ b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala
@@ -57,19 +57,14 @@ object ProtoTypes {
case pt: FunProto =>
mt match {
case mt: MethodType =>
- mt.isDependent || constrainResult(mt.resultType, pt.resultType)
+ constrainResult(resultTypeApprox(mt), pt.resultType)
case _ =>
true
}
case _: ValueTypeOrProto if !disregardProto(pt) =>
- mt match {
- case mt: MethodType =>
- mt.isDependent || isCompatible(normalize(mt, pt), pt)
- case _ =>
- isCompatible(mt, pt)
- }
- case _: WildcardType =>
- isCompatible(mt, pt)
+ isCompatible(normalize(mt, pt), pt)
+ case pt: WildcardType if pt.optBounds.exists =>
+ isCompatible(normalize(mt, pt), pt)
case _ =>
true
}
@@ -95,12 +90,12 @@ object ProtoTypes {
*
* [ ].name: proto
*/
- abstract case class SelectionProto(val name: Name, val memberProto: Type, val compat: Compatibility)
+ abstract case class SelectionProto(name: Name, memberProto: Type, compat: Compatibility, privateOK: Boolean)
extends CachedProxyType with ProtoType with ValueTypeOrProto {
override def isMatchedBy(tp1: Type)(implicit ctx: Context) = {
name == nme.WILDCARD || {
- val mbr = tp1.member(name)
+ val mbr = if (privateOK) tp1.member(name) else tp1.nonPrivateMember(name)
def qualifies(m: SingleDenotation) =
memberProto.isRef(defn.UnitClass) ||
compat.normalizedCompatible(m.info, memberProto)
@@ -115,11 +110,11 @@ object ProtoTypes {
def derivedSelectionProto(name: Name, memberProto: Type, compat: Compatibility)(implicit ctx: Context) =
if ((name eq this.name) && (memberProto eq this.memberProto) && (compat eq this.compat)) this
- else SelectionProto(name, memberProto, compat)
+ else SelectionProto(name, memberProto, compat, privateOK)
override def equals(that: Any): Boolean = that match {
case that: SelectionProto =>
- (name eq that.name) && (memberProto == that.memberProto) && (compat eq that.compat)
+ (name eq that.name) && (memberProto == that.memberProto) && (compat eq that.compat) && (privateOK == that.privateOK)
case _ =>
false
}
@@ -129,14 +124,18 @@ object ProtoTypes {
override def deepenProto(implicit ctx: Context) = derivedSelectionProto(name, memberProto.deepenProto, compat)
- override def computeHash = addDelta(doHash(name, memberProto), if (compat eq NoViewsAllowed) 1 else 0)
+ override def computeHash = {
+ val delta = (if (compat eq NoViewsAllowed) 1 else 0) | (if (privateOK) 2 else 0)
+ addDelta(doHash(name, memberProto), delta)
+ }
}
- class CachedSelectionProto(name: Name, memberProto: Type, compat: Compatibility) extends SelectionProto(name, memberProto, compat)
+ class CachedSelectionProto(name: Name, memberProto: Type, compat: Compatibility, privateOK: Boolean)
+ extends SelectionProto(name, memberProto, compat, privateOK)
object SelectionProto {
- def apply(name: Name, memberProto: Type, compat: Compatibility)(implicit ctx: Context): SelectionProto = {
- val selproto = new CachedSelectionProto(name, memberProto, compat)
+ def apply(name: Name, memberProto: Type, compat: Compatibility, privateOK: Boolean)(implicit ctx: Context): SelectionProto = {
+ val selproto = new CachedSelectionProto(name, memberProto, compat, privateOK)
if (compat eq NoViewsAllowed) unique(selproto) else selproto
}
}
@@ -148,7 +147,7 @@ object ProtoTypes {
if (name.isConstructorName) WildcardType
else tp match {
case tp: UnapplyFunProto => new UnapplySelectionProto(name)
- case tp => SelectionProto(name, IgnoredProto(tp), typer)
+ case tp => SelectionProto(name, IgnoredProto(tp), typer, privateOK = true)
}
/** A prototype for expressions [] that are in some unspecified selection operation
@@ -159,10 +158,10 @@ object ProtoTypes {
* operation is further selection. In this case, the expression need not be a value.
* @see checkValue
*/
- @sharable object AnySelectionProto extends SelectionProto(nme.WILDCARD, WildcardType, NoViewsAllowed)
+ @sharable object AnySelectionProto extends SelectionProto(nme.WILDCARD, WildcardType, NoViewsAllowed, true)
/** A prototype for selections in pattern constructors */
- class UnapplySelectionProto(name: Name) extends SelectionProto(name, WildcardType, NoViewsAllowed)
+ class UnapplySelectionProto(name: Name) extends SelectionProto(name, WildcardType, NoViewsAllowed, true)
trait ApplyingProto extends ProtoType
@@ -238,6 +237,12 @@ object ProtoTypes {
typer.adapt(targ, formal, arg)
}
+ /** The type of the argument `arg`.
+ * @pre `arg` has been typed before
+ */
+ def typeOfArg(arg: untpd.Tree)(implicit ctx: Context): Type =
+ myTypedArg(arg).tpe
+
private var myTupled: Type = NoType
/** The same proto-type but with all arguments combined in a single tuple */
@@ -394,6 +399,26 @@ object ProtoTypes {
/** Same as `constrained(pt, EmptyTree)`, but returns just the created polytype */
def constrained(pt: PolyType)(implicit ctx: Context): PolyType = constrained(pt, EmptyTree)._1
+ /** Create a new polyparam that represents a dependent method parameter singleton */
+ def newDepPolyParam(tp: Type)(implicit ctx: Context): PolyParam = {
+ val poly = PolyType(ctx.freshName(nme.DEP_PARAM_PREFIX).toTypeName :: Nil, 0 :: Nil)(
+ pt => TypeBounds.upper(AndType(tp, defn.SingletonType)) :: Nil,
+ pt => defn.AnyType)
+ ctx.typeComparer.addToConstraint(poly, Nil)
+ PolyParam(poly, 0)
+ }
+
+ /** The result type of `mt`, where all references to parameters of `mt` are
+ * replaced by either wildcards (if typevarsMissContext) or polyparams.
+ */
+ def resultTypeApprox(mt: MethodType)(implicit ctx: Context): Type =
+ if (mt.isDependent) {
+ def replacement(tp: Type) =
+ if (ctx.mode.is(Mode.TypevarsMissContext)) WildcardType else newDepPolyParam(tp)
+ mt.resultType.substParams(mt, mt.paramTypes.map(replacement))
+ }
+ else mt.resultType
+
/** The normalized form of a type
* - unwraps polymorphic types, tracking their parameters in the current constraint
* - skips implicit parameters; if result type depends on implicit parameter,
@@ -413,22 +438,18 @@ object ProtoTypes {
tp.widenSingleton match {
case poly: PolyType => normalize(constrained(poly).resultType, pt)
case mt: MethodType =>
- if (mt.isImplicit)
- if (mt.isDependent)
- mt.resultType.substParams(mt, mt.paramTypes.map(Function.const(WildcardType)))
- else mt.resultType
- else
- if (mt.isDependent) tp
- else {
- val rt = normalize(mt.resultType, pt)
+ if (mt.isImplicit) resultTypeApprox(mt)
+ else if (mt.isDependent) tp
+ else {
+ val rt = normalize(mt.resultType, pt)
pt match {
case pt: IgnoredProto => mt
case pt: ApplyingProto => mt.derivedMethodType(mt.paramNames, mt.paramTypes, rt)
case _ =>
val ft = defn.FunctionOf(mt.paramTypes, rt)
if (mt.paramTypes.nonEmpty || ft <:< pt) ft else rt
- }
}
+ }
case et: ExprType => et.resultType
case _ => tp
}
diff --git a/compiler/src/dotty/tools/dotc/typer/ReTyper.scala b/compiler/src/dotty/tools/dotc/typer/ReTyper.scala
index 3252ead47..6080c6644 100644
--- a/compiler/src/dotty/tools/dotc/typer/ReTyper.scala
+++ b/compiler/src/dotty/tools/dotc/typer/ReTyper.scala
@@ -85,8 +85,8 @@ class ReTyper extends Typer {
override def encodeName(tree: untpd.NameTree)(implicit ctx: Context) = tree
override def handleUnexpectedFunType(tree: untpd.Apply, fun: Tree)(implicit ctx: Context): Tree = fun.tpe match {
- case mt @ MethodType(_, formals) =>
- val args: List[Tree] = tree.args.zipWithConserve(formals)(typedExpr(_, _)).asInstanceOf[List[Tree]]
+ case mt: MethodType =>
+ val args: List[Tree] = tree.args.zipWithConserve(mt.paramTypes)(typedExpr(_, _)).asInstanceOf[List[Tree]]
assignType(untpd.cpy.Apply(tree)(fun, args), fun, args)
case _ =>
super.handleUnexpectedFunType(tree, fun)
diff --git a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala
index 7c573d23c..d61f5fa68 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()
}
@@ -744,11 +739,7 @@ import RefChecks._
*
* 2. It warns about references to symbols labeled deprecated or migration.
- * 3. It performs the following transformations:
- *
- * - if (true) A else B --> A
- * if (false) A else B --> B
- * - macro definitions are eliminated.
+ * 3. It eliminates macro definitions.
*
* 4. It makes members not private where necessary. The following members
* cannot be private in the Java model:
@@ -771,6 +762,9 @@ class RefChecks extends MiniPhase { thisTransformer =>
override def phaseName: String = "refchecks"
+ // Needs to run after ElimRepeated for override checks involving varargs methods
+ override def runsAfter = Set(classOf[ElimRepeated])
+
val treeTransform = new Transform(NoLevelInfo)
class Transform(currentLevel: RefChecks.OptLevelInfo = RefChecks.NoLevelInfo) extends TreeTransform {
@@ -838,12 +832,6 @@ class RefChecks extends MiniPhase { thisTransformer =>
tree
}
- override def transformIf(tree: If)(implicit ctx: Context, info: TransformerInfo) =
- tree.cond.tpe match {
- case ConstantType(value) => if (value.booleanValue) tree.thenp else tree.elsep
- case _ => tree
- }
-
override def transformNew(tree: New)(implicit ctx: Context, info: TransformerInfo) = {
currentLevel.enterReference(tree.tpe.typeSymbol, tree.pos)
tree
diff --git a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala
index 53ce5555b..6e774e38e 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 _ =>
@@ -318,10 +315,10 @@ trait TypeAssigner {
def assignType(tree: untpd.Apply, fn: Tree, args: List[Tree])(implicit ctx: Context) = {
val ownType = fn.tpe.widen match {
- case fntpe @ MethodType(_, ptypes) =>
- if (sameLength(ptypes, args) || ctx.phase.prev.relaxedTyping) fntpe.instantiate(args.tpes)
+ case fntpe: MethodType =>
+ if (sameLength(fntpe.paramTypes, args) || ctx.phase.prev.relaxedTyping) fntpe.instantiate(args.tpes)
else
- errorType(i"wrong number of arguments for $fntpe: ${fn.tpe}, expected: ${ptypes.length}, found: ${args.length}", tree.pos)
+ errorType(i"wrong number of arguments for $fntpe: ${fn.tpe}, expected: ${fntpe.paramTypes.length}, found: ${args.length}", tree.pos)
case t =>
errorType(i"${err.exprStr(fn)} does not take parameters", tree.pos)
}
@@ -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..d4a9744e4 100644
--- a/compiler/src/dotty/tools/dotc/typer/Typer.scala
+++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala
@@ -625,14 +625,17 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
block.tpe namedPartsWith (tp => locals.contains(tp.symbol))
}
- /** Check that expression's type can be expressed without references to locally defined
- * symbols. The following two remedies are tried before giving up:
- * 1. If the expected type of the expression is fully defined, pick it as the
- * type of the result expressed by adding a type ascription.
- * 2. If (1) fails, force all type variables so that the block's type is
- * fully defined and try again.
+ /** Ensure that an expression's type can be expressed without references to locally defined
+ * symbols. This is done by adding a type ascription of a widened type that does
+ * not refer to the locally defined symbols. The widened type is computed using
+ * `TyperAssigner#avoid`. However, if the expected type is fully defined and not
+ * a supertype of the widened type, we ascribe with the expected type instead.
+ *
+ * There's a special case having to do with anonymous classes. Sometimes the
+ * expected type of a block is the anonymous class defined inside it. In that
+ * case there's technically a leak which is not removed by the ascription.
*/
- protected def ensureNoLocalRefs(tree: Tree, pt: Type, localSyms: => List[Symbol], forcedDefined: Boolean = false)(implicit ctx: Context): Tree = {
+ protected def ensureNoLocalRefs(tree: Tree, pt: Type, localSyms: => List[Symbol])(implicit ctx: Context): Tree = {
def ascribeType(tree: Tree, pt: Type): Tree = tree match {
case block @ Block(stats, expr) =>
val expr1 = ascribeType(expr, pt)
@@ -640,16 +643,18 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
case _ =>
Typed(tree, TypeTree(pt.simplified))
}
- val leaks = escapingRefs(tree, localSyms)
- if (leaks.isEmpty) tree
- else if (isFullyDefined(pt, ForceDegree.none)) ascribeType(tree, pt)
- else if (!forcedDefined) {
+ def noLeaks(t: Tree): Boolean = escapingRefs(t, localSyms).isEmpty
+ if (noLeaks(tree)) tree
+ else {
fullyDefinedType(tree.tpe, "block", tree.pos)
- val tree1 = ascribeType(tree, avoid(tree.tpe, localSyms))
- ensureNoLocalRefs(tree1, pt, localSyms, forcedDefined = true)
- } else
- errorTree(tree,
- em"local definition of ${leaks.head.name} escapes as part of expression's type ${tree.tpe}"/*; full type: ${result.tpe.toString}"*/)
+ var avoidingType = avoid(tree.tpe, localSyms)
+ val ptDefined = isFullyDefined(pt, ForceDegree.none)
+ if (ptDefined && !(avoidingType <:< pt)) avoidingType = pt
+ val tree1 = ascribeType(tree, avoidingType)
+ assert(ptDefined || noLeaks(tree1), // `ptDefined` needed because of special case of anonymous classes
+ i"leak: ${escapingRefs(tree1, localSyms).toList}%, % in $tree1")
+ tree1
+ }
}
def typedIf(tree: untpd.If, pt: Type)(implicit ctx: Context): Tree = track("typedIf") {
@@ -667,8 +672,8 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
// this can type the greatest set of admissible closures.
(pt.dealias.argTypesLo.init, pt.dealias.argTypesHi.last)
case SAMType(meth) =>
- val mt @ MethodType(_, paramTypes) = meth.info
- (paramTypes, mt.resultType)
+ val MethodTpe(_, formals, restpe) = meth.info
+ (formals, restpe)
case _ =>
(List.range(0, defaultArity) map alwaysWildcardType, WildcardType)
}
@@ -1064,23 +1069,28 @@ 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)
+ if (tpt1.symbol.isClass)
+ tparam match {
+ case tparam: Symbol =>
+ // This is needed to get the test `compileParSetSubset` to work
+ tparam.ensureCompleted()
+ case _ =>
+ }
+ 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)
}
@@ -1219,6 +1229,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
completeAnnotations(ddef, sym)
val tparams1 = tparams mapconserve (typed(_).asInstanceOf[TypeDef])
val vparamss1 = vparamss nestedMapconserve (typed(_).asInstanceOf[ValDef])
+ vparamss1.foreach(checkNoForwardDependencies)
if (sym is Implicit) checkImplicitParamsNotSingletons(vparamss1)
var tpt1 = checkSimpleKinded(typedType(tpt))
@@ -1277,10 +1288,10 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
def maybeCall(ref: Tree, psym: Symbol, cinfo: Type): Tree = cinfo match {
case cinfo: PolyType =>
maybeCall(ref, psym, cinfo.resultType)
- case cinfo @ MethodType(Nil, _) if cinfo.resultType.isInstanceOf[ImplicitMethodType] =>
+ case cinfo @ MethodType(Nil) if cinfo.resultType.isInstanceOf[ImplicitMethodType] =>
val icall = New(ref).select(nme.CONSTRUCTOR).appliedToNone
typedExpr(untpd.TypedSplice(icall))(superCtx)
- case cinfo @ MethodType(Nil, _) if !cinfo.resultType.isInstanceOf[MethodType] =>
+ case cinfo @ MethodType(Nil) if !cinfo.resultType.isInstanceOf[MethodType] =>
ref
case cinfo: MethodType =>
if (!ctx.erasedTypes) { // after constructors arguments are passed in super call.
@@ -1316,6 +1327,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)
@@ -1715,7 +1727,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
def tryInsertImplicitOnQualifier(tree: Tree, pt: Type)(implicit ctx: Context): Option[Tree] = ctx.traceIndented(i"try insert impl on qualifier $tree $pt") {
tree match {
case Select(qual, name) =>
- val qualProto = SelectionProto(name, pt, NoViewsAllowed)
+ val qualProto = SelectionProto(name, pt, NoViewsAllowed, privateOK = false)
tryEither { implicit ctx =>
val qual1 = adaptInterpolated(qual, qualProto, EmptyTree)
if ((qual eq qual1) || ctx.reporter.hasErrors) None
@@ -2023,7 +2035,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/typer/Variances.scala b/compiler/src/dotty/tools/dotc/typer/Variances.scala
index 92bd9fd74..5a1745930 100644
--- a/compiler/src/dotty/tools/dotc/typer/Variances.scala
+++ b/compiler/src/dotty/tools/dotc/typer/Variances.scala
@@ -79,8 +79,8 @@ object Variances {
varianceInType(parent)(tparam) & varianceInType(rinfo)(tparam)
case tp: RecType =>
varianceInType(tp.parent)(tparam)
- case tp @ MethodType(_, paramTypes) =>
- flip(varianceInTypes(paramTypes)(tparam)) & varianceInType(tp.resultType)(tparam)
+ case tp: MethodType =>
+ flip(varianceInTypes(tp.paramTypes)(tparam)) & varianceInType(tp.resultType)(tparam)
case ExprType(restpe) =>
varianceInType(restpe)(tparam)
case tp @ HKApply(tycon, args) =>
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/dotc/tests.scala b/compiler/test/dotc/tests.scala
index a720f1294..01db2d9cc 100644
--- a/compiler/test/dotc/tests.scala
+++ b/compiler/test/dotc/tests.scala
@@ -224,6 +224,11 @@ class tests extends CompilerTest {
|../scala-scala/src/library/scala/collection/SeqLike.scala
|../scala-scala/src/library/scala/collection/generic/GenSeqFactory.scala""".stripMargin)
@Test def compileIndexedSeq = compileLine("../scala-scala/src/library/scala/collection/immutable/IndexedSeq.scala")
+ @Test def compileParSetLike = compileLine("../scala-scala/src/library/scala/collection/parallel/mutable/ParSetLike.scala")
+ @Test def compileParSetSubset = compileLine(
+ """../scala-scala/src/library/scala/collection/parallel/mutable/ParSetLike.scala
+ |../scala-scala/src/library/scala/collection/parallel/mutable/ParSet.scala
+ |../scala-scala/src/library/scala/collection/mutable/SetLike.scala""".stripMargin)(scala2mode ++ defaultOptions)
@Test def dotty = {
dottyBootedLib
@@ -355,7 +360,6 @@ class tests extends CompilerTest {
@Test def tasty_dotc_util = compileDir(dotcDir, "util", testPickling)
@Test def tasty_tools_io = compileDir(toolsDir, "io", testPickling)
- @Test def tasty_tests = compileDir(testsDir, "tasty", testPickling)
@Test def tasty_bootstrap = {
val logging = if (false) List("-Ylog-classpath", "-verbose") else Nil
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 d6e687a1e..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
@@ -212,4 +212,97 @@ class ErrorMessagesTests extends ErrorMessagesTest {
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/sbt-bridge/sbt-test/compilerReporter/simple/project/Reporter.scala b/sbt-bridge/sbt-test/compilerReporter/simple/project/Reporter.scala
index c0a56ec82..877da566c 100644
--- a/sbt-bridge/sbt-test/compilerReporter/simple/project/Reporter.scala
+++ b/sbt-bridge/sbt-test/compilerReporter/simple/project/Reporter.scala
@@ -37,8 +37,9 @@ object Reporter {
val problems = reporter.get.problems
println(problems.toList)
assert(problems.size == 2)
+ assert(problems.forall(_.position.offset.isDefined))
assert(problems.count(_.severity == Severity.Error) == 1) // not found: er1,
assert(problems.count(_.severity == Severity.Warn) == 1) // `with' as a type operator has been deprecated; use `&' instead,
})
)
-} \ No newline at end of file
+}
diff --git a/sbt-bridge/src/xsbt/DelegatingReporter.scala b/sbt-bridge/src/xsbt/DelegatingReporter.scala
index 770d6b2c7..e637ddcf3 100644
--- a/sbt-bridge/src/xsbt/DelegatingReporter.scala
+++ b/sbt-bridge/src/xsbt/DelegatingReporter.scala
@@ -27,15 +27,23 @@ final class DelegatingReporter(delegate: xsbti.Reporter) extends Reporter
case _ => xsbti.Severity.Info
}
- val position = new Position {
- def line: Maybe[Integer] = Maybe.nothing()
- def lineContent: String = ""
- def offset: Maybe[Integer] = Maybe.nothing()
- def pointer: Maybe[Integer] = Maybe.nothing()
- def pointerSpace: Maybe[String] = Maybe.nothing()
- def sourceFile: Maybe[java.io.File] = Maybe.nothing()
- def sourcePath: Maybe[String] = Maybe.nothing()
- }
+ val position =
+ if (cont.pos.exists) {
+ val pos = cont.pos
+ val src = pos.source
+ new Position {
+ val sourceFile: Maybe[java.io.File] = maybe(Option(src.file.file))
+ val sourcePath: Maybe[String] = maybe(Option(src.file.path))
+ val line: Maybe[Integer] = Maybe.just(pos.line)
+ val lineContent: String = pos.lineContent.stripLineEnd
+ val offset: Maybe[Integer] = Maybe.just(pos.point)
+ val pointer: Maybe[Integer] = Maybe.just(pos.point - src.startOfLine(pos.point))
+ val pointerSpace: Maybe[String] = Maybe.just(
+ ((lineContent: Seq[Char]).take(pointer.get).map { case '\t' => '\t'; case x => ' ' }).mkString
+ )
+ }
+ } else
+ noPosition
val sb = new StringBuilder()
sb.append(messageAndPos(cont.contained, cont.pos, diagnosticLevel(cont)))
@@ -45,4 +53,19 @@ final class DelegatingReporter(delegate: xsbti.Reporter) extends Reporter
delegate.log(position, sb.toString(), severity)
}
+
+ private[this] def maybe[T](opt: Option[T]): Maybe[T] = opt match {
+ case None => Maybe.nothing[T]
+ case Some(s) => Maybe.just[T](s)
+ }
+
+ private[this] val noPosition = new Position {
+ val line: Maybe[Integer] = Maybe.nothing[Integer]
+ val lineContent: String = ""
+ val offset: Maybe[Integer] = Maybe.nothing[Integer]
+ val pointer: Maybe[Integer] = Maybe.nothing[Integer]
+ val pointerSpace: Maybe[String] = Maybe.nothing[String]
+ val sourceFile: Maybe[java.io.File] = Maybe.nothing[java.io.File]
+ val sourcePath: Maybe[String] = Maybe.nothing[String]
+ }
}
diff --git a/tests/pending/pos/depmet_implicit_oopsla_session_simpler.scala b/tests/disabled/pos/depmet_implicit_oopsla_session_simpler.scala
index fad5eba40..8cc6fe754 100644
--- a/tests/pending/pos/depmet_implicit_oopsla_session_simpler.scala
+++ b/tests/disabled/pos/depmet_implicit_oopsla_session_simpler.scala
@@ -1,3 +1,4 @@
+// Disabled because we now get an unsafe instantiation error
object Sessions {
trait Session {
type Dual <: Session
@@ -40,5 +41,5 @@ object Sessions {
In{z: Int => System.out.println(z)
Stop()}}))
- def myRun = addServer run addClient
+ def myRun = addServer run addClient // error: unsafe instantiation
}
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/i1706.scala b/tests/neg/i1706.scala
new file mode 100644
index 000000000..b55ff6e2d
--- /dev/null
+++ b/tests/neg/i1706.scala
@@ -0,0 +1,3 @@
+object Test {
+ println (Object.reflect.runtime.universe.reify (new Object().getClass)) // error: not found Object
+}
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/i2066.scala b/tests/neg/i2066.scala
new file mode 100644
index 000000000..0081cec07
--- /dev/null
+++ b/tests/neg/i2066.scala
@@ -0,0 +1,27 @@
+class Foo
+
+object Test {
+ implicit def two(x: Foo): Two = new Two(x)
+
+ class Two(x: Foo) {
+ private def meth: Unit = {}
+
+ def test2(foo: Foo): Unit = {
+ foo.meth // error
+ }
+ }
+}
+
+
+object Test2 {
+
+ class Two(x: Foo) {
+ implicit def two(x: Foo): Two = new Two(x)
+
+ private def meth: Unit = {}
+
+ def test2(foo: Foo): Unit = {
+ foo.meth // error
+ }
+ }
+}
diff --git a/tests/neg/illegal-depmeth.scala b/tests/neg/illegal-depmeth.scala
new file mode 100644
index 000000000..e4d771a07
--- /dev/null
+++ b/tests/neg/illegal-depmeth.scala
@@ -0,0 +1,13 @@
+object Test {
+
+ class C { type T }
+
+ def f(x: C, y: x.T): x.T = y // ok
+
+ def g(y: x.T, x: C): x.T = y // error
+
+ def h(x: x.T) = ??? // error
+
+ def g(x: => C): x.T = ??? // error: x is not stable
+
+}
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/neg/t1569-failedAvoid.scala b/tests/neg/t1569-failedAvoid.scala
deleted file mode 100644
index 45bb96f36..000000000
--- a/tests/neg/t1569-failedAvoid.scala
+++ /dev/null
@@ -1,9 +0,0 @@
-// This was t1569.scala.
-// It fails in dotty because the expected type of the anonymous function in the last line
-// is fully determined (C). So that type is taken as the type of the anonymous function.
-// See pos/t1569a.scala for related examples that work.
-object Bug {
- class C { type T }
- def foo(x: Int)(y: C)(z: y.T): Unit = {}
- foo(3)(new C { type T = String })("hello") // error
-}
diff --git a/tests/pending/pos/depmet_implicit_oopsla_session_2.scala b/tests/pending/pos/depmet_implicit_oopsla_session_2.scala
index 29a76d5cf..26fa2a4cc 100644
--- a/tests/pending/pos/depmet_implicit_oopsla_session_2.scala
+++ b/tests/pending/pos/depmet_implicit_oopsla_session_2.scala
@@ -1,3 +1,8 @@
+// Fails on line 70 with: no implicit argument of type Sessions.Session[
+// | Sessions.In[Int, Sessions.In[Int, Sessions.Out[Int, Sessions.Stop]]]^
+// |]#HasDual[Sessions.Out[Int, Sessions.Out[Int, Sessions.In[Int, Sessions.Stop]]]^
+// | ] found for parameter evidence$1 of method runSession in object Sessions
+// This could be related to existential types (the # essentially boils down to one).
object Sessions {
def ?[T <: AnyRef](implicit w: T): w.type = w
diff --git a/tests/pickling/default-param-interface.scala b/tests/pickling/default-param-interface.scala
new file mode 100644
index 000000000..919f4b627
--- /dev/null
+++ b/tests/pickling/default-param-interface.scala
@@ -0,0 +1,3 @@
+trait Foo {
+ def newName(prefix: String = "foo"): String
+}
diff --git a/tests/tasty/i982.scala b/tests/pickling/i982.scala
index 838b250d9..838b250d9 100644
--- a/tests/tasty/i982.scala
+++ b/tests/pickling/i982.scala
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-java-interop/varargsOverride/Base.java b/tests/pos-java-interop/varargsOverride/Base.java
new file mode 100644
index 000000000..a4607b71c
--- /dev/null
+++ b/tests/pos-java-interop/varargsOverride/Base.java
@@ -0,0 +1,5 @@
+class Base {
+ public Object foo(Object... x) {
+ return x;
+ }
+}
diff --git a/tests/pos-java-interop/varargsOverride/Sub.scala b/tests/pos-java-interop/varargsOverride/Sub.scala
new file mode 100644
index 000000000..9d3e2bf0d
--- /dev/null
+++ b/tests/pos-java-interop/varargsOverride/Sub.scala
@@ -0,0 +1,3 @@
+class Sub extends Base {
+ override def foo(x: Object*): Object = x
+}
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/pending/pos/depmet_implicit_norm_ret.scala b/tests/pos/depmet_implicit_norm_ret.scala
index 42bfb9fe1..42bfb9fe1 100644
--- a/tests/pending/pos/depmet_implicit_norm_ret.scala
+++ b/tests/pos/depmet_implicit_norm_ret.scala
diff --git a/tests/pos/erased-lub-2.scala b/tests/pos/erased-lub-2.scala
new file mode 100644
index 000000000..f0f9b27cc
--- /dev/null
+++ b/tests/pos/erased-lub-2.scala
@@ -0,0 +1,15 @@
+trait Foo
+
+trait PF[A, +B] {
+ def apply(x: A): B
+}
+
+object Test {
+ def orElse2[A1, B1 >: Foo](that: PF[A1, B1]): PF[A1, B1] = ???
+
+ def identity[E]: PF[E, E] = ???
+
+ def foo: PF[Foo, Foo] = ???
+
+ def bla(foo: Foo) = orElse2(identity).apply(foo)
+}
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/i2064.scala b/tests/pos/i2064.scala
new file mode 100644
index 000000000..909923372
--- /dev/null
+++ b/tests/pos/i2064.scala
@@ -0,0 +1,15 @@
+object p {
+
+class Foo[T] {
+ // Crashes:
+ def f(): Foo[T] = (if (true) this else this).bar
+
+ // Works:
+ // def f(): Foo[T] = new Bar(if (true) this else this).bar
+}
+
+implicit class Bar[A](val self: A) {
+ def bar(): A = self
+}
+
+}
diff --git a/tests/pos/i2066.scala b/tests/pos/i2066.scala
new file mode 100644
index 000000000..505e5e334
--- /dev/null
+++ b/tests/pos/i2066.scala
@@ -0,0 +1,15 @@
+class Foo
+
+object Test {
+ implicit class One(x: Foo) {
+ def meth: Unit = {}
+ }
+
+ implicit class Two(x: Foo) {
+ private def meth: Unit = {}
+ }
+
+ def test(foo: Foo): Unit = {
+ foo.meth
+ }
+}
diff --git a/tests/pos/i2071.scala b/tests/pos/i2071.scala
new file mode 100644
index 000000000..1855dccf4
--- /dev/null
+++ b/tests/pos/i2071.scala
@@ -0,0 +1,7 @@
+object Test {
+ type PF[A, B] = PartialFunction[A, B]
+
+ val f: PF[Int, String] = {
+ case i => "bar"
+ }
+} \ No newline at end of file
diff --git a/tests/pos/param-depmeth.scala b/tests/pos/param-depmeth.scala
new file mode 100644
index 000000000..2e887d181
--- /dev/null
+++ b/tests/pos/param-depmeth.scala
@@ -0,0 +1,15 @@
+object Test {
+
+ class C { type T }
+
+ def f(x: C, y: x.T): x.T = y // ok
+
+ val c = new C { type T = String }
+ val c2 = c
+
+ f(c, "abc")
+ f(new C{ type T = String}, "abc")
+
+ val d: (C{ type T = String}) # T = "abc"
+
+}
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/t1569.scala b/tests/pos/t1569.scala
new file mode 100644
index 000000000..a2fbcf11f
--- /dev/null
+++ b/tests/pos/t1569.scala
@@ -0,0 +1,12 @@
+// See pos/t1569a.scala for related examples that work.
+object Bug {
+ class C { type T }
+ def foo(x: Int)(y: C)(z: y.T): Unit = {}
+ foo(3)(new C { type T = String })("hello")
+}
+object Bug2 {
+ class C { type T }
+ class D extends C { type T = String }
+ def foo(x: Int)(y: C)(z: y.T): Unit = {}
+ foo(3)(new D {})("hello")
+}
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/pos/t5070.scala b/tests/pos/t5070.scala
index 410afba14..0e5c0ffc0 100644
--- a/tests/pos/t5070.scala
+++ b/tests/pos/t5070.scala
@@ -13,3 +13,26 @@ class Test {
implicitly[a.T](b(a)) // works
}
+
+
+class ImplicitVsTypeAliasTezt {
+
+ class Monad[m[_]] {
+ type For[a] = _For[m, a]
+ implicit def toFor[a](m: m[a]): For[a] = throw new Error("todo") // lookup fails
+// implicit def toFor[a](m: m[a]): _For[m, a] = throw new Error("todo") // fine.
+ }
+
+ trait _For[m[_], a] {
+ def map[b](p: a => b): m[b]
+ }
+
+ def useMonad[m[_], a](m: m[a])(implicit i: Monad[m]) = {
+ import i._
+
+ // value map is not a member of type parameter m[a]
+ for {
+ x <- m
+ } yield x.toString
+ }
+}
diff --git a/tests/pos/t5643.scala b/tests/pos/t5643.scala
new file mode 100644
index 000000000..1ce34ba36
--- /dev/null
+++ b/tests/pos/t5643.scala
@@ -0,0 +1,19 @@
+object TupledEvidenceTest {
+
+ abstract class TupledEvidence[M[_], T0] { type T = T0 }
+
+ implicit def witnessTuple2[M[_], T1, T2](implicit ev1: M[T1], ev2: M[T2]):
+ TupledEvidence[M, (T1, T2)] { type T = (T1, T2) } = sys.error("")
+
+ class GetResult[T]
+
+ implicit val getString: GetResult[String] = new GetResult[String]
+
+ implicit def getTuple[T](implicit w: TupledEvidence[GetResult, T]): GetResult[w.T] = sys.error("")
+
+ def f[T : GetResult] = ""
+
+ f[(String,String)](getTuple[(String, String)])
+
+ f[(String,String)]
+}
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/HLists-nonvariant.check b/tests/run/HLists-nonvariant.check
new file mode 100644
index 000000000..53efe30d7
--- /dev/null
+++ b/tests/run/HLists-nonvariant.check
@@ -0,0 +1,8 @@
+1
+A
+true
+true
+HCons(1,HCons(A,HCons(true,HNil)))
+1
+A
+true
diff --git a/tests/run/HLists-nonvariant.scala b/tests/run/HLists-nonvariant.scala
new file mode 100644
index 000000000..a3a639bcd
--- /dev/null
+++ b/tests/run/HLists-nonvariant.scala
@@ -0,0 +1,78 @@
+sealed trait HList
+case class HCons[HD, TL](hd: HD, tl: TL) extends HList
+case object HNil extends HList
+
+sealed trait Num
+case object Zero extends Num
+case class Succ[N <: Num](pred: N) extends Num
+
+object Test {
+
+ type HNil = HNil.type
+ type Zero = Zero.type
+
+ trait Concat[Xs <: HList, Ys <: HList, Zs <: HList] {
+ def concat(xs: Xs, ys: Ys): Zs
+ }
+
+ implicit def concatNil[Xs <: HList]: Concat[HNil, Xs, Xs] =
+ new Concat[HNil, Xs, Xs] {
+ def concat(fst: HNil, snd: Xs) = snd
+ }
+
+ implicit def concatCons[X, Xs <: HList, Ys <: HList, Zs <: HList](
+ implicit ev: Concat[Xs, Ys, Zs]
+ ): Concat[HCons[X, Xs], Ys, HCons[X, Zs]] =
+ new Concat[HCons[X, Xs], Ys, HCons[X, Zs]] {
+ def concat(xs: HCons[X, Xs], ys: Ys): HCons[X, Zs] =
+ HCons(xs.hd, ev.concat(xs.tl, ys))
+ }
+
+ def concat[Xs <: HList, Ys <: HList, Zs <: HList](xs: Xs, ys: Ys)(implicit ev: Concat[Xs, Ys, Zs]): Zs =
+ ev.concat(xs, ys)
+
+ val xs = HCons(1, HCons("A", HNil))
+ val ys = HCons(true, HNil)
+ val zs = concat(xs, ys)
+ val zs1: HCons[Int, HCons[String, HCons[Boolean, HNil]]] = zs
+
+ trait At[Xs <: HList, N <: Num] {
+ type Out
+ def at(xs: Xs, n: N): Out
+ }
+
+ implicit def atZero[XZ, Xs <: HList]: At[HCons[XZ, Xs], Zero] { type Out = XZ } =
+ new At[HCons[XZ, Xs], Zero] {
+ type Out = XZ
+ def at(xs: HCons[XZ, Xs], n: Zero) = xs.hd
+ }
+
+ implicit def atSucc[XX, Xs <: HList, N <: Num](
+ implicit ev: At[Xs, N]
+ ): At[HCons[XX, Xs], Succ[N]] { type Out = ev.Out } = new At[HCons[XX, Xs], Succ[N]] {
+ type Out = ev.Out
+ def at(xs: HCons[XX, Xs], n: Succ[N]): Out = ev.at(xs.tl, n.pred)
+ }
+
+ def at[Xs <: HList, N <: Num](xs: Xs, n: N)(
+ implicit ev: At[Xs, N]
+ ): ev.Out = ev.at(xs, n)
+
+ def main(args: Array[String]) = {
+ val ys1 = HCons(1, HNil)
+ println(at(ys1, Zero))
+
+ val ys2 = HCons(1, HCons("A", HNil))
+ val y2 = at(ys2, Succ(Zero))
+ println(at(ys2, Succ(Zero)))
+ val ys3 = HCons(1, HCons("A", HCons(true, HNil)))
+ println(at(ys3, Succ(Succ(Zero))))
+ val ys4 = HCons(1, HCons("A", HCons(true, HCons(1.0, HNil))))
+ println(at(ys4, Succ(Succ(Zero))))
+
+ println(zs1)
+ println(at(zs1, Zero))
+ println(at(zs1, Succ(Zero)))
+ println(at(zs1, Succ(Succ(Zero))))
+ }
+}
diff --git a/tests/run/HLists.check b/tests/run/HLists.check
new file mode 100644
index 000000000..53efe30d7
--- /dev/null
+++ b/tests/run/HLists.check
@@ -0,0 +1,8 @@
+1
+A
+true
+true
+HCons(1,HCons(A,HCons(true,HNil)))
+1
+A
+true
diff --git a/tests/run/HLists.scala b/tests/run/HLists.scala
new file mode 100644
index 000000000..eebbcb4cd
--- /dev/null
+++ b/tests/run/HLists.scala
@@ -0,0 +1,78 @@
+sealed trait HList
+case class HCons[+HD, +TL](hd: HD, tl: TL) extends HList
+case object HNil extends HList
+
+sealed trait Num
+case object Zero extends Num
+case class Succ[N <: Num](pred: N) extends Num
+
+object Test {
+
+ type HNil = HNil.type
+ type Zero = Zero.type
+
+ trait Concat[Xs <: HList, Ys <: HList, Zs <: HList] {
+ def concat(xs: Xs, ys: Ys): Zs
+ }
+
+ implicit def concatNil[Xs <: HList]: Concat[HNil, Xs, Xs] =
+ new Concat[HNil, Xs, Xs] {
+ def concat(fst: HNil, snd: Xs) = snd
+ }
+
+ implicit def concatCons[X, Xs <: HList, Ys <: HList, Zs <: HList](
+ implicit ev: Concat[Xs, Ys, Zs]
+ ): Concat[HCons[X, Xs], Ys, HCons[X, Zs]] =
+ new Concat[HCons[X, Xs], Ys, HCons[X, Zs]] {
+ def concat(xs: HCons[X, Xs], ys: Ys): HCons[X, Zs] =
+ HCons(xs.hd, ev.concat(xs.tl, ys))
+ }
+
+ def concat[Xs <: HList, Ys <: HList, Zs <: HList](xs: Xs, ys: Ys)(implicit ev: Concat[Xs, Ys, Zs]): Zs =
+ ev.concat(xs, ys)
+
+ val xs = HCons(1, HCons("A", HNil))
+ val ys = HCons(true, HNil)
+ val zs = concat(xs, ys)
+ val zs1: HCons[Int, HCons[String, HCons[Boolean, HNil]]] = zs
+
+ trait At[Xs <: HList, N <: Num] {
+ type Out
+ def at(xs: Xs, n: N): Out
+ }
+
+ implicit def atZero[XZ, Xs <: HList]: At[HCons[XZ, Xs], Zero] { type Out = XZ } =
+ new At[HCons[XZ, Xs], Zero] {
+ type Out = XZ
+ def at(xs: HCons[XZ, Xs], n: Zero) = xs.hd
+ }
+
+ implicit def atSucc[XX, Xs <: HList, N <: Num](
+ implicit ev: At[Xs, N]
+ ): At[HCons[XX, Xs], Succ[N]] { type Out = ev.Out } = new At[HCons[XX, Xs], Succ[N]] {
+ type Out = ev.Out
+ def at(xs: HCons[XX, Xs], n: Succ[N]): Out = ev.at(xs.tl, n.pred)
+ }
+
+ def at[Xs <: HList, N <: Num](xs: Xs, n: N)(
+ implicit ev: At[Xs, N]
+ ): ev.Out = ev.at(xs, n)
+
+ def main(args: Array[String]) = {
+ val ys1 = HCons(1, HNil)
+ println(at(ys1, Zero))
+
+ val ys2 = HCons(1, HCons("A", HNil))
+ val y2 = at(ys2, Succ(Zero))
+ println(at(ys2, Succ(Zero)))
+ val ys3 = HCons(1, HCons("A", HCons(true, HNil)))
+ println(at(ys3, Succ(Succ(Zero))))
+ val ys4 = HCons(1, HCons("A", HCons(true, HCons(1.0, HNil))))
+ println(at(ys4, Succ(Succ(Zero))))
+
+ println(zs1)
+ println(at(zs1, Zero))
+ println(at(zs1, Succ(Zero)))
+ println(at(zs1, Succ(Succ(Zero))))
+ }
+}
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/hmap-covariant.scala b/tests/run/hmap-covariant.scala
new file mode 100644
index 000000000..475cc6ee6
--- /dev/null
+++ b/tests/run/hmap-covariant.scala
@@ -0,0 +1,97 @@
+trait Tuple
+case class TCons[+H, +T <: Tuple](h: H, t: T) extends Tuple
+final case object TNil extends Tuple
+
+// Type level natural numbers -------------------------------------------------
+
+sealed trait Nat
+sealed trait Succ[P <: Nat] extends Nat
+sealed trait Zero extends Nat
+
+// Accessor type class to compute the N'th element of an Tuple L --------------
+
+trait At[L <: Tuple, N <: Nat, Out] {
+ def apply(l: L): Out
+}
+
+object At {
+ implicit def caseZero[H, T <: Tuple]: At[H TCons T, Zero, H] =
+ new At[H TCons T, Zero, H] {
+ def apply(l: H TCons T): H = {
+ val (h TCons _) = l
+ h
+ }
+ }
+
+ implicit def caseN[H, T <: Tuple, N <: Nat, O]
+ (implicit a: At[T, N, O]): At[H TCons T, Succ[N], O] =
+ new At[H TCons T, Succ[N], O] {
+ def apply(l: H TCons T): O = {
+ val (_ TCons t) = l
+ a(t)
+ }
+ }
+}
+
+// An HMap is an Tuple with HEntry elements. We are reusing Tuple for it's nice syntax
+
+final case class HEntry[K, V](value: V)
+
+// Accessor type class to compute the element of type K in a HMap L -----------
+
+trait PhantomGet[K, M <: Tuple, I <: Nat] // extends PhantomAny
+
+object PhantomGet {
+ implicit def getHead[K, V, T <: Tuple]
+ : PhantomGet[K, HEntry[K, V] TCons T, Zero] = null
+
+ implicit def getTail[K, H, T <: Tuple, I <: Nat]
+ (implicit t: PhantomGet[K, T, I])
+ : PhantomGet[K, H TCons T, Succ[I]] = null
+}
+
+// Syntax ---------------------------------------------------------------------
+
+object syntax {
+ object hmap {
+ implicit class HmapGet[M <: Tuple](m: M) {
+ def get[K, V, I <: Nat](k: K)
+ (implicit
+ g: PhantomGet[k.type, M, I],
+ a: At[M, I, HEntry[k.type, V]]
+ ): V = a(m).value
+ }
+
+ def --[K, V](key: K, value: V) = HEntry[key.type, V](value)
+ }
+}
+
+object Test {
+ def main(args: Array[String]): Unit = {
+ import syntax.hmap._
+
+ val map1 =
+ TCons(HEntry[K = "name"]("foo"),
+ TCons(HEntry[K = "genre"](true),
+ TCons(HEntry[K = "moneyz"](123),
+ TCons(HEntry[K = "cat"]("bar"),
+ (TNil: TNil.type)))))
+
+ assert(map1.get("name") == "foo")
+ assert(map1.get("genre") == true)
+ assert(map1.get("moneyz") == 123)
+ assert(map1.get("cat") == "bar")
+
+ val map2 =
+ TCons(--("name" , "foo"),
+ TCons(--("genre" , true),
+ TCons(--("moneyz", 123),
+ TCons(--("cat" , "bar"),
+ TNil))))
+
+ assert(map2.get("name") == "foo")
+ assert(map2.get("genre") == true)
+ assert(map2.get("moneyz") == 123)
+ assert(map2.get("cat") == "bar")
+ }
+}
diff --git a/tests/run/i1960.scala b/tests/run/i1960.scala
new file mode 100644
index 000000000..a3d441d17
--- /dev/null
+++ b/tests/run/i1960.scala
@@ -0,0 +1,8 @@
+case class CC2[A, B](_1: A, _2: B)
+
+object Test {
+ def main(args: Array[String]): Unit = {
+ val CC2(_, CC2(a, _)) = CC2(0, CC2(1, 2))
+ assert(a == 1)
+ }
+}
diff --git a/tests/run/i2004.check b/tests/run/i2004.check
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/tests/run/i2004.check
@@ -0,0 +1 @@
+1
diff --git a/tests/run/i2004.scala b/tests/run/i2004.scala
new file mode 100644
index 000000000..ff21a6cc9
--- /dev/null
+++ b/tests/run/i2004.scala
@@ -0,0 +1,11 @@
+object Test {
+ def main(args: Array[String]) = {
+ val f: (Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int,Int, Int, Int, Int, Int, Int, Int, Int, Int, Int) => Int =
+ {
+ (x1: Int, x2: Int, x3: Int, x4: Int, x5: Int, x6: Int, x7: Int, x8: Int, x9: Int, x10: Int, x11: Int, x12: Int, x13: Int, x14: Int, x15: Int, x16: Int, x17: Int, x18: Int, x19: Int, x20: Int, x21: Int, x22: Int, x23: Int, x24: Int, x25: Int, x26: Int) =>
+ x1
+ }
+ println(f.apply(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1))
+
+ }
+}
diff --git a/tests/run/i2077.check b/tests/run/i2077.check
new file mode 100644
index 000000000..45b983be3
--- /dev/null
+++ b/tests/run/i2077.check
@@ -0,0 +1 @@
+hi
diff --git a/tests/run/i2077.scala b/tests/run/i2077.scala
new file mode 100644
index 000000000..42b629b90
--- /dev/null
+++ b/tests/run/i2077.scala
@@ -0,0 +1,10 @@
+object Test {
+ inline val x = true
+ val y = if (x) 1 else 2 // reduced to val y = 1
+
+ def main(args: Array[String]): Unit =
+ if ({ println("hi"); true }) // cannot be reduced
+ 1
+ else
+ 2
+}
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)
}