aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/src/dotty/tools/backend/jvm/GenBCode.scala22
-rw-r--r--compiler/src/dotty/tools/backend/jvm/scalaPrimitives.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/ast/Desugar.scala133
-rw-r--r--compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala200
-rw-r--r--compiler/src/dotty/tools/dotc/ast/TreeInfo.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/ast/Trees.scala18
-rw-r--r--compiler/src/dotty/tools/dotc/ast/tpd.scala14
-rw-r--r--compiler/src/dotty/tools/dotc/ast/untpd.scala15
-rw-r--r--compiler/src/dotty/tools/dotc/config/Config.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/config/ScalaSettings.scala1
-rw-r--r--compiler/src/dotty/tools/dotc/core/Constants.scala4
-rw-r--r--compiler/src/dotty/tools/dotc/core/Constraint.scala60
-rw-r--r--compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala58
-rw-r--r--compiler/src/dotty/tools/dotc/core/Contexts.scala5
-rw-r--r--compiler/src/dotty/tools/dotc/core/Decorators.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/core/Definitions.scala16
-rw-r--r--compiler/src/dotty/tools/dotc/core/Denotations.scala56
-rw-r--r--compiler/src/dotty/tools/dotc/core/Flags.scala17
-rw-r--r--compiler/src/dotty/tools/dotc/core/Mode.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/core/NameOps.scala26
-rw-r--r--compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala154
-rw-r--r--compiler/src/dotty/tools/dotc/core/ParamInfo.scala (renamed from compiler/src/dotty/tools/dotc/core/TypeParamInfo.scala)22
-rw-r--r--compiler/src/dotty/tools/dotc/core/StdNames.scala13
-rw-r--r--compiler/src/dotty/tools/dotc/core/Substituters.scala6
-rw-r--r--compiler/src/dotty/tools/dotc/core/SymDenotations.scala20
-rw-r--r--compiler/src/dotty/tools/dotc/core/Symbols.scala12
-rw-r--r--compiler/src/dotty/tools/dotc/core/TypeApplications.scala65
-rw-r--r--compiler/src/dotty/tools/dotc/core/TypeComparer.scala146
-rw-r--r--compiler/src/dotty/tools/dotc/core/TypeErasure.scala22
-rw-r--r--compiler/src/dotty/tools/dotc/core/TypeOps.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/core/TyperState.scala8
-rw-r--r--compiler/src/dotty/tools/dotc/core/Types.scala760
-rw-r--r--compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala6
-rw-r--r--compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala21
-rw-r--r--compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/core/tasty/TreeBuffer.scala1
-rw-r--r--compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala34
-rw-r--r--compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala43
-rw-r--r--compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala16
-rw-r--r--compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala4
-rw-r--r--compiler/src/dotty/tools/dotc/parsing/Parsers.scala179
-rw-r--r--compiler/src/dotty/tools/dotc/parsing/Scanners.scala67
-rw-r--r--compiler/src/dotty/tools/dotc/parsing/Tokens.scala8
-rw-r--r--compiler/src/dotty/tools/dotc/printing/Formatting.scala16
-rw-r--r--compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala26
-rw-r--r--compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala6
-rw-r--r--compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala6
-rw-r--r--compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala18
-rw-r--r--compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala4
-rw-r--r--compiler/src/dotty/tools/dotc/transform/CollectEntryPoints.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/transform/ElimByName.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/transform/ElimErasedValueType.scala4
-rw-r--r--compiler/src/dotty/tools/dotc/transform/ElimRepeated.scala10
-rw-r--r--compiler/src/dotty/tools/dotc/transform/Erasure.scala12
-rw-r--r--compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/transform/FullParameterization.scala14
-rw-r--r--compiler/src/dotty/tools/dotc/transform/FunctionalInterfaces.scala6
-rw-r--r--compiler/src/dotty/tools/dotc/transform/MixinOps.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/transform/PostTyper.scala10
-rw-r--r--compiler/src/dotty/tools/dotc/transform/ShortcutImplicits.scala4
-rw-r--r--compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala8
-rw-r--r--compiler/src/dotty/tools/dotc/transform/TailRec.scala4
-rw-r--r--compiler/src/dotty/tools/dotc/transform/TreeChecker.scala10
-rw-r--r--compiler/src/dotty/tools/dotc/transform/VCInlineMethods.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Applications.scala45
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Checking.scala47
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Dynamic.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala12
-rw-r--r--compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala8
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Implicits.scala15
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Inferencing.scala14
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Inliner.scala9
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Namer.scala17
-rw-r--r--compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala60
-rw-r--r--compiler/src/dotty/tools/dotc/typer/ReTyper.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala20
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Typer.scala44
-rw-r--r--compiler/src/dotty/tools/dotc/typer/VarianceChecker.scala6
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Variances.scala8
-rw-r--r--compiler/test/dotty/tools/dotc/parsing/DocstringTests.scala30
-rw-r--r--compiler/test/dotty/tools/dotc/repl/TestREPL.scala7
-rw-r--r--doc-tool/resources/_layouts/main.html1
-rw-r--r--doc-tool/resources/_layouts/sidebar.html9
-rw-r--r--doc-tool/resources/css/dottydoc.css118
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/core/DocASTPhase.scala5
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/model/factories.scala14
-rw-r--r--docs/docs/internals/syntax.md15
-rw-r--r--library/src/scala/Enum.scala8
-rw-r--r--library/src/scala/runtime/EnumValues.scala21
-rw-r--r--tests/neg/enums.scala20
-rw-r--r--tests/neg/leak-type.scala13
-rw-r--r--tests/pos/enum-List-control.scala14
-rw-r--r--tests/pos/i1130.scala4
-rw-r--r--tests/pos/leak-inferred.scala12
-rw-r--r--tests/pos/tailcall/i2024.scala4
-rw-r--r--tests/pos/tailcall/return.scala2
-rw-r--r--tests/run/enum-Color.check3
-rw-r--r--tests/run/enum-Color.scala11
-rw-r--r--tests/run/enum-HList.scala22
-rw-r--r--tests/run/enum-List1.check1
-rw-r--r--tests/run/enum-List1.scala10
-rw-r--r--tests/run/enum-List2.check1
-rw-r--r--tests/run/enum-List2.scala11
-rw-r--r--tests/run/enum-List2a.check1
-rw-r--r--tests/run/enum-List2a.scala11
-rw-r--r--tests/run/enum-List3.check1
-rw-r--r--tests/run/enum-List3.scala10
-rw-r--r--tests/run/enum-Option.scala19
-rw-r--r--tests/run/enum-Tree.check1
-rw-r--r--tests/run/enum-Tree.scala29
-rw-r--r--tests/run/enum-approx.scala22
-rw-r--r--tests/run/enumList2a.check1
-rw-r--r--tests/run/generic/Color.scala13
-rw-r--r--tests/run/generic/Enum.scala18
-rw-r--r--tests/run/generic/List.scala2
-rw-r--r--tests/run/generic/SearchResult.scala17
-rw-r--r--tests/run/generic/Tree.scala6
-rw-r--r--tests/run/planets.check8
-rw-r--r--tests/run/planets.scala26
120 files changed, 2052 insertions, 1234 deletions
diff --git a/compiler/src/dotty/tools/backend/jvm/GenBCode.scala b/compiler/src/dotty/tools/backend/jvm/GenBCode.scala
index 65dcb6c79..8fd6d1bc0 100644
--- a/compiler/src/dotty/tools/backend/jvm/GenBCode.scala
+++ b/compiler/src/dotty/tools/backend/jvm/GenBCode.scala
@@ -1,19 +1,18 @@
package dotty.tools.backend.jvm
import dotty.tools.dotc.CompilationUnit
-import dotty.tools.dotc.ast.Trees.{ValDef, PackageDef}
+import dotty.tools.dotc.ast.Trees.{PackageDef, ValDef}
import dotty.tools.dotc.ast.tpd
import dotty.tools.dotc.core.Phases.Phase
import dotty.tools.dotc.core.Names.TypeName
import scala.collection.mutable
-import scala.tools.asm.{CustomAttr, ClassVisitor, MethodVisitor, FieldVisitor}
+import scala.tools.asm.{ClassVisitor, CustomAttr, FieldVisitor, MethodVisitor}
import scala.tools.nsc.Settings
import scala.tools.nsc.backend.jvm._
import dotty.tools.dotc
import dotty.tools.dotc.backend.jvm.DottyPrimitives
import dotty.tools.dotc.transform.Erasure
-
import dotty.tools.dotc.interfaces
import java.util.Optional
@@ -27,14 +26,15 @@ import Symbols._
import Denotations._
import Phases._
import java.lang.AssertionError
-import java.io.{ File => JFile }
+import java.io.{FileOutputStream, File => JFile}
+
import scala.tools.asm
import scala.tools.asm.tree._
-import dotty.tools.dotc.util.{Positions, DotClass}
+import dotty.tools.dotc.util.{DotClass, Positions}
import tpd._
import StdNames._
-import scala.reflect.io.{Directory, PlainDirectory, AbstractFile}
+import scala.reflect.io.{AbstractFile, Directory, PlainDirectory}
import scala.tools.nsc.backend.jvm.opt.LocalOpt
class GenBCode extends Phase {
@@ -205,7 +205,15 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter
if (claszSymbol.isClass) // @DarkDimius is this test needed here?
for (binary <- ctx.compilationUnit.pickled.get(claszSymbol.asClass)) {
val dataAttr = new CustomAttr(nme.TASTYATTR.toString, binary)
- (if (mirrorC ne null) mirrorC else plainC).visitAttribute(dataAttr)
+ val store = if (mirrorC ne null) mirrorC else plainC
+ store.visitAttribute(dataAttr)
+ if (ctx.settings.emitTasty.value) {
+ val outTastyFile = getFileForClassfile(outF, store.name, ".tasty").file
+ val fos = new FileOutputStream(outTastyFile, false)
+ fos.write(binary)
+ fos.close()
+
+ }
}
// -------------- bean info class, if needed --------------
diff --git a/compiler/src/dotty/tools/backend/jvm/scalaPrimitives.scala b/compiler/src/dotty/tools/backend/jvm/scalaPrimitives.scala
index 89831e56b..7beae90c4 100644
--- a/compiler/src/dotty/tools/backend/jvm/scalaPrimitives.scala
+++ b/compiler/src/dotty/tools/backend/jvm/scalaPrimitives.scala
@@ -142,7 +142,7 @@ class DottyPrimitives(ctx: Context) {
ctx.error(s"Unknown primitive method $cls.$method")
else alts foreach (s =>
addPrimitive(s,
- s.info.paramTypess match {
+ s.info.paramInfoss match {
case List(tp :: _) if code == ADD && tp =:= ctx.definitions.StringType => CONCAT
case _ => code
}
diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala
index 75c7078a1..66fc6bf84 100644
--- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala
+++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala
@@ -14,6 +14,7 @@ import reporting.diagnostic.messages._
object desugar {
import untpd._
+ import DesugarEnums._
/** Tags a .withFilter call generated by desugaring a for expression.
* Such calls can alternatively be rewritten to use filter.
@@ -153,8 +154,8 @@ object desugar {
case ContextBounds(tbounds, cxbounds) =>
epbuf ++= makeImplicitParameters(cxbounds, isPrimaryConstructor)
tbounds
- case PolyTypeTree(tparams, body) =>
- cpy.PolyTypeTree(rhs)(tparams, desugarContextBounds(body))
+ case LambdaTypeTree(tparams, body) =>
+ cpy.LambdaTypeTree(rhs)(tparams, desugarContextBounds(body))
case _ =>
rhs
}
@@ -263,7 +264,9 @@ object desugar {
val className = checkNotReservedName(cdef).asTypeName
val impl @ Template(constr0, parents, self, _) = cdef.rhs
val mods = cdef.mods
- val companionMods = mods.withFlags((mods.flags & AccessFlags).toCommonFlags)
+ val companionMods = mods
+ .withFlags((mods.flags & AccessFlags).toCommonFlags)
+ .withMods(mods.mods.filter(!_.isInstanceOf[Mod.EnumCase]))
val (constr1, defaultGetters) = defDef(constr0, isPrimaryConstructor = true) match {
case meth: DefDef => (meth, Nil)
@@ -288,17 +291,31 @@ object desugar {
}
val isCaseClass = mods.is(Case) && !mods.is(Module)
+ val isEnum = mods.hasMod[Mod.Enum]
+ val isEnumCase = isLegalEnumCase(cdef)
val isValueClass = parents.nonEmpty && isAnyVal(parents.head)
// This is not watertight, but `extends AnyVal` will be replaced by `inline` later.
- val constrTparams = constr1.tparams map toDefParam
+ lazy val reconstitutedTypeParams = reconstitutedEnumTypeParams(cdef.pos.startPos)
+
+ val originalTparams =
+ if (isEnumCase && parents.isEmpty) {
+ if (constr1.tparams.nonEmpty) {
+ if (reconstitutedTypeParams.nonEmpty)
+ ctx.error(em"case with type parameters needs extends clause", constr1.tparams.head.pos)
+ constr1.tparams
+ }
+ else reconstitutedTypeParams
+ }
+ else constr1.tparams
+ val originalVparamss = constr1.vparamss
+ val constrTparams = originalTparams.map(toDefParam)
val constrVparamss =
- if (constr1.vparamss.isEmpty) { // ensure parameter list is non-empty
- if (isCaseClass)
- ctx.error(CaseClassMissingParamList(cdef), cdef.namePos)
+ if (originalVparamss.isEmpty) { // ensure parameter list is non-empty
+ if (isCaseClass) ctx.error(CaseClassMissingParamList(cdef), cdef.namePos)
ListOfNil
}
- else constr1.vparamss.nestedMap(toDefParam)
+ else originalVparamss.nestedMap(toDefParam)
val constr = cpy.DefDef(constr1)(tparams = constrTparams, vparamss = constrVparamss)
// Add constructor type parameters and evidence implicit parameters
@@ -312,21 +329,24 @@ object desugar {
stat
}
- val derivedTparams = constrTparams map derivedTypeParam
+ val derivedTparams =
+ if (isEnumCase) constrTparams else constrTparams map derivedTypeParam
val derivedVparamss = constrVparamss nestedMap derivedTermParam
val arity = constrVparamss.head.length
- var classTycon: Tree = EmptyTree
+ val classTycon: Tree = new TypeRefTree // watching is set at end of method
- // a reference to the class type, with all parameters given.
- val classTypeRef/*: Tree*/ = {
- // -language:keepUnions difference: classTypeRef needs type annotation, otherwise
- // infers Ident | AppliedTypeTree, which
- // renders the :\ in companions below untypable.
- classTycon = (new TypeRefTree) withPos cdef.pos.startPos // watching is set at end of method
- val tparams = impl.constr.tparams
- if (tparams.isEmpty) classTycon else AppliedTypeTree(classTycon, tparams map refOfDef)
- }
+ def appliedRef(tycon: Tree) =
+ (if (constrTparams.isEmpty) tycon
+ else AppliedTypeTree(tycon, constrTparams map refOfDef))
+ .withPos(cdef.pos.startPos)
+
+ // a reference to the class type bound by `cdef`, with type parameters coming from the constructor
+ val classTypeRef = appliedRef(classTycon)
+ // a reference to `enumClass`, with type parameters coming from the constructor
+ lazy val enumClassTypeRef =
+ if (reconstitutedTypeParams.isEmpty) enumClassRef
+ else appliedRef(enumClassRef)
// new C[Ts](paramss)
lazy val creatorExpr = New(classTypeRef, constrVparamss nestedMap refOfDef)
@@ -374,7 +394,9 @@ object desugar {
DefDef(nme.copy, derivedTparams, copyFirstParams :: copyRestParamss, TypeTree(), creatorExpr)
.withMods(synthetic) :: Nil
}
- copyMeths ::: productElemMeths.toList
+
+ val enumTagMeths = if (isEnumCase) enumTagMeth(CaseKind.Class)._1 :: Nil else Nil
+ copyMeths ::: enumTagMeths ::: productElemMeths.toList
}
else Nil
@@ -387,8 +409,12 @@ object desugar {
// Case classes and case objects get a ProductN parent
var parents1 = parents
+ if (isEnumCase && parents.isEmpty)
+ parents1 = enumClassTypeRef :: Nil
if (mods.is(Case) && arity <= Definitions.MaxTupleArity)
- parents1 = parents1 :+ productConstr(arity)
+ parents1 = parents1 :+ productConstr(arity) // TODO: This also adds Product0 to caes objects. Do we want that?
+ if (isEnum)
+ parents1 = parents1 :+ ref(defn.EnumType)
// The thicket which is the desugared version of the companion object
// synthetic object C extends parentTpt { defs }
@@ -410,17 +436,26 @@ object desugar {
// For all other classes, the parent is AnyRef.
val companions =
if (isCaseClass) {
+ // The return type of the `apply` method
+ val applyResultTpt =
+ if (isEnumCase)
+ if (parents.isEmpty) enumClassTypeRef
+ else parents.reduceLeft(AndTypeTree)
+ else TypeTree()
+
val parent =
if (constrTparams.nonEmpty ||
constrVparamss.length > 1 ||
mods.is(Abstract) ||
constr.mods.is(Private)) anyRef
+ else
// todo: also use anyRef if constructor has a dependent method type (or rule that out)!
- else (constrVparamss :\ classTypeRef) ((vparams, restpe) => Function(vparams map (_.tpt), restpe))
+ (constrVparamss :\ (if (isEnumCase) applyResultTpt else classTypeRef)) (
+ (vparams, restpe) => Function(vparams map (_.tpt), restpe))
val applyMeths =
if (mods is Abstract) Nil
else
- DefDef(nme.apply, derivedTparams, derivedVparamss, TypeTree(), creatorExpr)
+ DefDef(nme.apply, derivedTparams, derivedVparamss, applyResultTpt, creatorExpr)
.withFlags(Synthetic | (constr1.mods.flags & DefaultParameterized)) :: Nil
val unapplyMeth = {
val unapplyParam = makeSyntheticParameter(tpt = classTypeRef)
@@ -464,15 +499,15 @@ object desugar {
else cpy.ValDef(self)(tpt = selfType).withMods(self.mods | SelfName)
}
- val cdef1 = {
- val originalTparams = constr1.tparams.toIterator
- val originalVparams = constr1.vparamss.toIterator.flatten
- val tparamAccessors = derivedTparams.map(_.withMods(originalTparams.next.mods))
+ val cdef1 = addEnumFlags {
+ val originalTparamsIt = originalTparams.toIterator
+ val originalVparamsIt = originalVparamss.toIterator.flatten
+ val tparamAccessors = derivedTparams.map(_.withMods(originalTparamsIt.next.mods))
val caseAccessor = if (isCaseClass) CaseAccessor else EmptyFlags
val vparamAccessors = derivedVparamss match {
case first :: rest =>
- first.map(_.withMods(originalVparams.next.mods | caseAccessor)) ++
- rest.flatten.map(_.withMods(originalVparams.next.mods))
+ first.map(_.withMods(originalVparamsIt.next.mods | caseAccessor)) ++
+ rest.flatten.map(_.withMods(originalVparamsIt.next.mods))
case _ =>
Nil
}
@@ -503,23 +538,26 @@ object desugar {
*/
def moduleDef(mdef: ModuleDef)(implicit ctx: Context): Tree = {
val moduleName = checkNotReservedName(mdef).asTermName
- val tmpl = mdef.impl
+ val impl = mdef.impl
val mods = mdef.mods
+ lazy val isEnumCase = isLegalEnumCase(mdef)
if (mods is Package)
- PackageDef(Ident(moduleName), cpy.ModuleDef(mdef)(nme.PACKAGE, tmpl).withMods(mods &~ Package) :: Nil)
+ PackageDef(Ident(moduleName), cpy.ModuleDef(mdef)(nme.PACKAGE, impl).withMods(mods &~ Package) :: Nil)
+ else if (isEnumCase)
+ expandEnumModule(moduleName, impl, mods, mdef.pos)
else {
val clsName = moduleName.moduleClassName
val clsRef = Ident(clsName)
val modul = ValDef(moduleName, clsRef, New(clsRef, Nil))
.withMods(mods | ModuleCreationFlags | mods.flags & AccessFlags)
.withPos(mdef.pos)
- val ValDef(selfName, selfTpt, _) = tmpl.self
- val selfMods = tmpl.self.mods
- if (!selfTpt.isEmpty) ctx.error(ObjectMayNotHaveSelfType(mdef), tmpl.self.pos)
- val clsSelf = ValDef(selfName, SingletonTypeTree(Ident(moduleName)), tmpl.self.rhs)
+ val ValDef(selfName, selfTpt, _) = impl.self
+ val selfMods = impl.self.mods
+ if (!selfTpt.isEmpty) ctx.error(ObjectMayNotHaveSelfType(mdef), impl.self.pos)
+ val clsSelf = ValDef(selfName, SingletonTypeTree(Ident(moduleName)), impl.self.rhs)
.withMods(selfMods)
- .withPos(tmpl.self.pos orElse tmpl.pos.startPos)
- val clsTmpl = cpy.Template(tmpl)(self = clsSelf, body = tmpl.body)
+ .withPos(impl.self.pos orElse impl.pos.startPos)
+ val clsTmpl = cpy.Template(impl)(self = clsSelf, body = impl.body)
val cls = TypeDef(clsName, clsTmpl)
.withMods(mods.toTypeFlags & RetainedModuleClassFlags | ModuleClassCreationFlags)
Thicket(modul, classDef(cls).withPos(mdef.pos))
@@ -542,11 +580,23 @@ object desugar {
/** val p1, ..., pN: T = E
* ==>
* makePatDef[[val p1: T1 = E]]; ...; makePatDef[[val pN: TN = E]]
+ *
+ * case e1, ..., eN
+ * ==>
+ * expandSimpleEnumCase([case e1]); ...; expandSimpleEnumCase([case eN])
*/
- def patDef(pdef: PatDef)(implicit ctx: Context): Tree = {
+ def patDef(pdef: PatDef)(implicit ctx: Context): Tree = flatTree {
val PatDef(mods, pats, tpt, rhs) = pdef
- val pats1 = if (tpt.isEmpty) pats else pats map (Typed(_, tpt))
- flatTree(pats1 map (makePatDef(pdef, mods, _, rhs)))
+ if (mods.hasMod[Mod.EnumCase] && enumCaseIsLegal(pdef))
+ pats map {
+ case id: Ident =>
+ expandSimpleEnumCase(id.name.asTermName, mods,
+ Position(pdef.pos.start, id.pos.end, id.pos.start))
+ }
+ else {
+ val pats1 = if (tpt.isEmpty) pats else pats map (Typed(_, tpt))
+ pats1 map (makePatDef(pdef, mods, _, rhs))
+ }
}
/** If `pat` is a variable pattern,
@@ -923,7 +973,7 @@ object desugar {
case (gen: GenFrom) :: (rest @ (GenFrom(_, _) :: _)) =>
val cont = makeFor(mapName, flatMapName, rest, body)
Apply(rhsSelect(gen, flatMapName), makeLambda(gen.pat, cont))
- case (enum @ GenFrom(pat, rhs)) :: (rest @ GenAlias(_, _) :: _) =>
+ case (GenFrom(pat, rhs)) :: (rest @ GenAlias(_, _) :: _) =>
val (valeqs, rest1) = rest.span(_.isInstanceOf[GenAlias])
val pats = valeqs map { case GenAlias(pat, _) => pat }
val rhss = valeqs map { case GenAlias(_, rhs) => rhs }
@@ -1024,7 +1074,6 @@ object desugar {
List(CaseDef(Ident(nme.DEFAULT_EXCEPTION_NAME), EmptyTree, Apply(handler, Ident(nme.DEFAULT_EXCEPTION_NAME)))),
finalizer)
}
-
}
}.withPos(tree.pos)
diff --git a/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala b/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala
new file mode 100644
index 000000000..43f915961
--- /dev/null
+++ b/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala
@@ -0,0 +1,200 @@
+package dotty.tools
+package dotc
+package ast
+
+import core._
+import util.Positions._, Types._, Contexts._, Constants._, Names._, NameOps._, Flags._
+import SymDenotations._, Symbols._, StdNames._, Annotations._, Trees._
+import Decorators._
+import collection.mutable.ListBuffer
+import util.Property
+import typer.ErrorReporting._
+
+/** Helper methods to desugar enums */
+object DesugarEnums {
+ import untpd._
+ import desugar.DerivedFromParamTree
+
+ @sharable object CaseKind extends Enumeration {
+ val Simple, Object, Class = Value
+ }
+
+ /** Attachment containing the number of enum cases and the smallest kind that was seen so far. */
+ val EnumCaseCount = new Property.Key[(Int, CaseKind.Value)]
+
+ /** the enumeration class that is a companion of the current object */
+ def enumClass(implicit ctx: Context) = ctx.owner.linkedClass
+
+ /** Is this an enum case that's situated in a companion object of an enum class? */
+ def isLegalEnumCase(tree: MemberDef)(implicit ctx: Context): Boolean =
+ tree.mods.hasMod[Mod.EnumCase] && enumCaseIsLegal(tree)
+
+ /** Is enum case `tree` situated in a companion object of an enum class? */
+ def enumCaseIsLegal(tree: Tree)(implicit ctx: Context): Boolean = (
+ ctx.owner.is(ModuleClass) && enumClass.derivesFrom(defn.EnumClass)
+ || { ctx.error(em"case not allowed here, since owner ${ctx.owner} is not an `enum' object", tree.pos)
+ false
+ }
+ )
+
+ /** Type parameters reconstituted from the constructor
+ * of the `enum' class corresponding to an enum case.
+ * The variance is the same as the corresponding type parameter of the enum class.
+ */
+ def reconstitutedEnumTypeParams(pos: Position)(implicit ctx: Context) = {
+ val tparams = enumClass.primaryConstructor.info match {
+ case info: PolyType =>
+ ctx.newTypeParams(ctx.newLocalDummy(enumClass), info.paramNames, EmptyFlags, info.instantiateBounds)
+ case _ =>
+ Nil
+ }
+ (tparams, enumClass.typeParams).zipped.map { (tparam, ecTparam) =>
+ val tbounds = new DerivedFromParamTree
+ tbounds.pushAttachment(OriginalSymbol, tparam)
+ TypeDef(tparam.name, tbounds)
+ .withFlags(Param | PrivateLocal | ecTparam.flags & VarianceFlags).withPos(pos)
+ }
+ }
+
+ /** A reference to the enum class `E`, possibly followed by type arguments.
+ * Each covariant type parameter is approximated by its lower bound.
+ * Each contravariant type parameter is approximated by its upper bound.
+ * It is an error if a type parameter is non-variant, or if its approximation
+ * refers to pther type parameters.
+ */
+ def interpolatedEnumParent(pos: Position)(implicit ctx: Context): Tree = {
+ val tparams = enumClass.typeParams
+ def isGround(tp: Type) = tp.subst(tparams, tparams.map(_ => NoType)) eq tp
+ val targs = tparams map { tparam =>
+ if (tparam.variance > 0 && isGround(tparam.info.bounds.lo))
+ tparam.info.bounds.lo
+ else if (tparam.variance < 0 && isGround(tparam.info.bounds.hi))
+ tparam.info.bounds.hi
+ else {
+ def problem =
+ if (tparam.variance == 0) "is non variant"
+ else "has bounds that depend on a type parameter in the same parameter list"
+ errorType(i"""cannot determine type argument for enum parent $enumClass,
+ |type parameter $tparam $problem""", pos)
+ }
+ }
+ TypeTree(enumClass.typeRef.appliedTo(targs)).withPos(pos)
+ }
+
+ /** A type tree referring to `enumClass` */
+ def enumClassRef(implicit ctx: Context) = TypeTree(enumClass.typeRef)
+
+ /** Add implied flags to an enum class or an enum case */
+ def addEnumFlags(cdef: TypeDef)(implicit ctx: Context) =
+ if (cdef.mods.hasMod[Mod.Enum]) cdef.withFlags(cdef.mods.flags | Abstract | Sealed)
+ else if (isLegalEnumCase(cdef)) cdef.withFlags(cdef.mods.flags | Final)
+ else cdef
+
+ private def valuesDot(name: String) = Select(Ident(nme.DOLLAR_VALUES), name.toTermName)
+ private def registerCall(implicit ctx: Context): List[Tree] =
+ if (enumClass.typeParams.nonEmpty) Nil
+ else Apply(valuesDot("register"), This(EmptyTypeIdent) :: Nil) :: Nil
+
+ /** The following lists of definitions for an enum type E:
+ *
+ * private val $values = new EnumValues[E]
+ * def enumValue = $values.fromInt
+ * def enumValueNamed = $values.fromName
+ * def enumValues = $values.values
+ */
+ private def enumScaffolding(implicit ctx: Context): List[Tree] = {
+ def enumDefDef(name: String, select: String) =
+ DefDef(name.toTermName, Nil, Nil, TypeTree(), valuesDot(select))
+ val privateValuesDef =
+ ValDef(nme.DOLLAR_VALUES, TypeTree(),
+ New(TypeTree(defn.EnumValuesType.appliedTo(enumClass.typeRef :: Nil)), ListOfNil))
+ .withFlags(Private)
+ val valueOfDef = enumDefDef("enumValue", "fromInt")
+ val withNameDef = enumDefDef("enumValueNamed", "fromName")
+ val valuesDef = enumDefDef("enumValues", "values")
+ List(privateValuesDef, valueOfDef, withNameDef, valuesDef)
+ }
+
+ /** A creation method for a value of enum type `E`, which is defined as follows:
+ *
+ * private def $new(tag: Int, name: String) = new E {
+ * def enumTag = tag
+ * override def toString = name
+ * $values.register(this)
+ * }
+ */
+ private def enumValueCreator(implicit ctx: Context) = {
+ def param(name: TermName, typ: Type) =
+ ValDef(name, TypeTree(typ), EmptyTree).withFlags(Param)
+ val enumTagDef =
+ DefDef(nme.enumTag, Nil, Nil, TypeTree(), Ident(nme.tag))
+ val toStringDef =
+ DefDef(nme.toString_, Nil, Nil, TypeTree(), Ident(nme.name))
+ .withFlags(Override)
+ def creator = New(Template(emptyConstructor, enumClassRef :: Nil, EmptyValDef,
+ List(enumTagDef, toStringDef) ++ registerCall))
+ DefDef(nme.DOLLAR_NEW, Nil,
+ List(List(param(nme.tag, defn.IntType), param(nme.name, defn.StringType))),
+ TypeTree(), creator)
+ }
+
+ /** A pair consisting of
+ * - the next enum tag
+ * - scaffolding containing the necessary definitions for singleton enum cases
+ * unless that scaffolding was already generated by a previous call to `nextEnumKind`.
+ */
+ def nextEnumTag(kind: CaseKind.Value)(implicit ctx: Context): (Int, List[Tree]) = {
+ val (count, seenKind) = ctx.tree.removeAttachment(EnumCaseCount).getOrElse((0, CaseKind.Class))
+ val minKind = if (kind < seenKind) kind else seenKind
+ ctx.tree.pushAttachment(EnumCaseCount, (count + 1, minKind))
+ val scaffolding =
+ if (enumClass.typeParams.nonEmpty || kind >= seenKind) Nil
+ else if (kind == CaseKind.Object) enumScaffolding
+ else if (seenKind == CaseKind.Object) enumValueCreator :: Nil
+ else enumScaffolding :+ enumValueCreator
+ (count, scaffolding)
+ }
+
+ /** A pair consisting of
+ * - a method returning the next enum tag
+ * - scaffolding as defined in `nextEnumTag`
+ */
+ def enumTagMeth(kind: CaseKind.Value)(implicit ctx: Context): (DefDef, List[Tree]) = {
+ val (tag, scaffolding) = nextEnumTag(kind)
+ (DefDef(nme.enumTag, Nil, Nil, TypeTree(), Literal(Constant(tag))), scaffolding)
+ }
+
+ /** Expand a module definition representing a parameterless enum case */
+ def expandEnumModule(name: TermName, impl: Template, mods: Modifiers, pos: Position)(implicit ctx: Context): Tree =
+ if (impl.parents.isEmpty)
+ if (impl.body.isEmpty)
+ expandSimpleEnumCase(name, mods, pos)
+ else {
+ val parent = interpolatedEnumParent(pos)
+ expandEnumModule(name, cpy.Template(impl)(parents = parent :: Nil), mods, pos)
+ }
+ else {
+ def toStringMeth =
+ DefDef(nme.toString_, Nil, Nil, TypeTree(defn.StringType), Literal(Constant(name.toString)))
+ .withFlags(Override)
+ val (tagMeth, scaffolding) = enumTagMeth(CaseKind.Object)
+ val impl1 = cpy.Template(impl)(body =
+ impl.body ++ List(tagMeth, toStringMeth) ++ registerCall)
+ val vdef = ValDef(name, TypeTree(), New(impl1)).withMods(mods | Final).withPos(pos)
+ flatTree(scaffolding ::: vdef :: Nil).withPos(pos.startPos)
+ }
+
+ /** Expand a simple enum case */
+ def expandSimpleEnumCase(name: TermName, mods: Modifiers, pos: Position)(implicit ctx: Context): Tree =
+ if (enumClass.typeParams.nonEmpty) {
+ val parent = interpolatedEnumParent(pos)
+ val impl = Template(emptyConstructor, parent :: Nil, EmptyValDef, Nil)
+ expandEnumModule(name, impl, mods, pos)
+ }
+ else {
+ val (tag, scaffolding) = nextEnumTag(CaseKind.Simple)
+ val creator = Apply(Ident(nme.DOLLAR_NEW), List(Literal(Constant(tag)), Literal(Constant(name.toString))))
+ val vdef = ValDef(name, enumClassRef, creator).withMods(mods | Final).withPos(pos)
+ flatTree(scaffolding ::: vdef :: Nil).withPos(pos.startPos)
+ }
+}
diff --git a/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala b/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala
index b00d7df71..037ab73af 100644
--- a/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala
+++ b/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala
@@ -262,7 +262,7 @@ trait UntypedTreeInfo extends TreeInfo[Untyped] { self: Trees.Instance[Untyped]
case mdef: TypeDef =>
def isBounds(rhs: Tree): Boolean = rhs match {
case _: TypeBoundsTree => true
- case PolyTypeTree(_, body) => isBounds(body)
+ case LambdaTypeTree(_, body) => isBounds(body)
case _ => false
}
mdef.rhs.isEmpty || isBounds(mdef.rhs)
diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala
index 669e5429c..0fc47a8a4 100644
--- a/compiler/src/dotty/tools/dotc/ast/Trees.scala
+++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala
@@ -578,9 +578,9 @@ object Trees {
}
/** [typeparams] -> tpt */
- case class PolyTypeTree[-T >: Untyped] private[ast] (tparams: List[TypeDef[T]], body: Tree[T])
+ case class LambdaTypeTree[-T >: Untyped] private[ast] (tparams: List[TypeDef[T]], body: Tree[T])
extends TypTree[T] {
- type ThisTree[-T >: Untyped] = PolyTypeTree[T]
+ type ThisTree[-T >: Untyped] = LambdaTypeTree[T]
}
/** => T */
@@ -833,7 +833,7 @@ object Trees {
type OrTypeTree = Trees.OrTypeTree[T]
type RefinedTypeTree = Trees.RefinedTypeTree[T]
type AppliedTypeTree = Trees.AppliedTypeTree[T]
- type PolyTypeTree = Trees.PolyTypeTree[T]
+ type LambdaTypeTree = Trees.LambdaTypeTree[T]
type ByNameTypeTree = Trees.ByNameTypeTree[T]
type TypeBoundsTree = Trees.TypeBoundsTree[T]
type Bind = Trees.Bind[T]
@@ -998,9 +998,9 @@ object Trees {
case tree: AppliedTypeTree if (tpt eq tree.tpt) && (args eq tree.args) => tree
case _ => finalize(tree, untpd.AppliedTypeTree(tpt, args))
}
- def PolyTypeTree(tree: Tree)(tparams: List[TypeDef], body: Tree): PolyTypeTree = tree match {
- case tree: PolyTypeTree if (tparams eq tree.tparams) && (body eq tree.body) => tree
- case _ => finalize(tree, untpd.PolyTypeTree(tparams, body))
+ def LambdaTypeTree(tree: Tree)(tparams: List[TypeDef], body: Tree): LambdaTypeTree = tree match {
+ case tree: LambdaTypeTree if (tparams eq tree.tparams) && (body eq tree.body) => tree
+ case _ => finalize(tree, untpd.LambdaTypeTree(tparams, body))
}
def ByNameTypeTree(tree: Tree)(result: Tree): ByNameTypeTree = tree match {
case tree: ByNameTypeTree if result eq tree.result => tree
@@ -1144,8 +1144,8 @@ object Trees {
cpy.RefinedTypeTree(tree)(transform(tpt), transformSub(refinements))
case AppliedTypeTree(tpt, args) =>
cpy.AppliedTypeTree(tree)(transform(tpt), transform(args))
- case PolyTypeTree(tparams, body) =>
- cpy.PolyTypeTree(tree)(transformSub(tparams), transform(body))
+ case LambdaTypeTree(tparams, body) =>
+ cpy.LambdaTypeTree(tree)(transformSub(tparams), transform(body))
case ByNameTypeTree(result) =>
cpy.ByNameTypeTree(tree)(transform(result))
case TypeBoundsTree(lo, hi) =>
@@ -1248,7 +1248,7 @@ object Trees {
this(this(x, tpt), refinements)
case AppliedTypeTree(tpt, args) =>
this(this(x, tpt), args)
- case PolyTypeTree(tparams, body) =>
+ case LambdaTypeTree(tparams, body) =>
implicit val ctx = localCtx
this(this(x, tparams), body)
case ByNameTypeTree(result) =>
diff --git a/compiler/src/dotty/tools/dotc/ast/tpd.scala b/compiler/src/dotty/tools/dotc/ast/tpd.scala
index cbb256dd0..ff66c8c8e 100644
--- a/compiler/src/dotty/tools/dotc/ast/tpd.scala
+++ b/compiler/src/dotty/tools/dotc/ast/tpd.scala
@@ -145,8 +145,8 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
def ByNameTypeTree(result: Tree)(implicit ctx: Context): ByNameTypeTree =
ta.assignType(untpd.ByNameTypeTree(result), result)
- def PolyTypeTree(tparams: List[TypeDef], body: Tree)(implicit ctx: Context): PolyTypeTree =
- ta.assignType(untpd.PolyTypeTree(tparams, body), tparams, body)
+ def LambdaTypeTree(tparams: List[TypeDef], body: Tree)(implicit ctx: Context): LambdaTypeTree =
+ ta.assignType(untpd.LambdaTypeTree(tparams, body), tparams, body)
def TypeBoundsTree(lo: Tree, hi: Tree)(implicit ctx: Context): TypeBoundsTree =
ta.assignType(untpd.TypeBoundsTree(lo, hi), lo, hi)
@@ -190,7 +190,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
val maybeImplicit = if (tp.isInstanceOf[ImplicitMethodType]) Implicit else EmptyFlags
ctx.newSymbol(sym, name, TermParam | maybeImplicit, info)
}
- val params = (tp.paramNames, tp.paramTypes).zipped.map(valueParam)
+ val params = (tp.paramNames, tp.paramInfos).zipped.map(valueParam)
val (paramss, rtp) = valueParamss(tp.instantiate(params map (_.termRef)))
(params :: paramss, rtp)
case tp => (Nil, tp.widenExpr)
@@ -221,7 +221,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
case ctpe: PolyType =>
isApplicable(ctpe.instantiate(firstParent.argTypes))
case ctpe: MethodType =>
- (superArgs corresponds ctpe.paramTypes)(_.tpe <:< _)
+ (superArgs corresponds ctpe.paramInfos)(_.tpe <:< _)
case _ =>
false
}
@@ -836,7 +836,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
val selected =
if (denot.isOverloaded) {
def typeParamCount(tp: Type) = tp.widen match {
- case tp: PolyType => tp.paramBounds.length
+ case tp: PolyType => tp.paramInfos.length
case _ => 0
}
var allAlts = denot.alternatives
@@ -859,7 +859,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
def adaptLastArg(lastParam: Tree, expectedType: Type) = {
if (isAnnotConstructor && !(lastParam.tpe <:< expectedType)) {
val defn = ctx.definitions
- val prefix = args.take(selected.widen.paramTypess.head.size - 1)
+ val prefix = args.take(selected.widen.paramInfoss.head.size - 1)
expectedType match {
case defn.ArrayOf(el) =>
lastParam.tpe match {
@@ -878,7 +878,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
}
val callArgs: List[Tree] = if (args.isEmpty) Nil else {
- val expectedType = selected.widen.paramTypess.head.last
+ val expectedType = selected.widen.paramInfoss.head.last
val lastParam = args.last
adaptLastArg(lastParam, expectedType)
}
diff --git a/compiler/src/dotty/tools/dotc/ast/untpd.scala b/compiler/src/dotty/tools/dotc/ast/untpd.scala
index 9b55720b8..7a9f2fe66 100644
--- a/compiler/src/dotty/tools/dotc/ast/untpd.scala
+++ b/compiler/src/dotty/tools/dotc/ast/untpd.scala
@@ -9,6 +9,7 @@ import Decorators._
import util.Property
import language.higherKinds
import collection.mutable.ListBuffer
+import reflect.ClassTag
object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
@@ -132,6 +133,10 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
case class Inline() extends Mod(Flags.Inline)
case class Type() extends Mod(Flags.EmptyFlags)
+
+ case class Enum() extends Mod(Flags.EmptyFlags)
+
+ case class EnumCase() extends Mod(Flags.EmptyFlags)
}
/** Modifiers and annotations for definitions
@@ -185,6 +190,10 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
def hasFlags = flags != EmptyFlags
def hasAnnotations = annotations.nonEmpty
def hasPrivateWithin = privateWithin != tpnme.EMPTY
+ def hasMod[T: ClassTag] = {
+ val cls = implicitly[ClassTag[T]].runtimeClass
+ mods.exists(mod => cls.isAssignableFrom(mod.getClass))
+ }
}
@sharable val EmptyModifiers: Modifiers = new Modifiers()
@@ -261,7 +270,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
def OrTypeTree(left: Tree, right: Tree): OrTypeTree = new OrTypeTree(left, right)
def RefinedTypeTree(tpt: Tree, refinements: List[Tree]): RefinedTypeTree = new RefinedTypeTree(tpt, refinements)
def AppliedTypeTree(tpt: Tree, args: List[Tree]): AppliedTypeTree = new AppliedTypeTree(tpt, args)
- def PolyTypeTree(tparams: List[TypeDef], body: Tree): PolyTypeTree = new PolyTypeTree(tparams, body)
+ def LambdaTypeTree(tparams: List[TypeDef], body: Tree): LambdaTypeTree = new LambdaTypeTree(tparams, body)
def ByNameTypeTree(result: Tree): ByNameTypeTree = new ByNameTypeTree(result)
def TypeBoundsTree(lo: Tree, hi: Tree): TypeBoundsTree = new TypeBoundsTree(lo, hi)
def Bind(name: Name, body: Tree): Bind = new Bind(name, body)
@@ -352,7 +361,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
ValDef(nme.syntheticParamName(n), tpt, EmptyTree).withFlags(SyntheticTermParam)
def lambdaAbstract(tparams: List[TypeDef], tpt: Tree)(implicit ctx: Context) =
- if (tparams.isEmpty) tpt else PolyTypeTree(tparams, tpt)
+ if (tparams.isEmpty) tpt else LambdaTypeTree(tparams, tpt)
/** A reference to given definition. If definition is a repeated
* parameter, the reference will be a repeated argument.
@@ -477,7 +486,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
case SymbolLit(str) =>
cpy.SymbolLit(tree)(str)
case InterpolatedString(id, segments) =>
- cpy.InterpolatedString(tree)(id, segments.map(transform(_)))
+ cpy.InterpolatedString(tree)(id, segments.mapConserve(transform))
case Function(args, body) =>
cpy.Function(tree)(transform(args), transform(body))
case InfixOp(left, op, right) =>
diff --git a/compiler/src/dotty/tools/dotc/config/Config.scala b/compiler/src/dotty/tools/dotc/config/Config.scala
index 903efd794..46b1896f1 100644
--- a/compiler/src/dotty/tools/dotc/config/Config.scala
+++ b/compiler/src/dotty/tools/dotc/config/Config.scala
@@ -40,7 +40,7 @@ object Config {
* accesses javac's settings.)
*
* It is recommended to turn this option on only when chasing down
- * a PolyParam instantiation error. See comment in Types.TypeVar.instantiate.
+ * a TypeParamRef instantiation error. See comment in Types.TypeVar.instantiate.
*/
final val debugCheckConstraintsClosed = false
diff --git a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala
index 318295751..49b64d869 100644
--- a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala
+++ b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala
@@ -71,6 +71,7 @@ class ScalaSettings extends Settings.SettingGroup {
val debugOwners = BooleanSetting("-Ydebug-owners", "Print all owners of definitions (requires -Yprint-syms)")
val termConflict = ChoiceSetting("-Yresolve-term-conflict", "strategy", "Resolve term conflicts", List("package", "object", "error"), "error")
val log = PhasesSetting("-Ylog", "Log operations during")
+ val emitTasty = BooleanSetting("-YemitTasty", "Generate tasty in separate *.tasty file.")
val Ylogcp = BooleanSetting("-Ylog-classpath", "Output information about what classpath is being applied.")
val YnoImports = BooleanSetting("-Yno-imports", "Compile without importing scala.*, java.lang.*, or Predef.")
val YnoPredef = BooleanSetting("-Yno-predef", "Compile without importing Predef.")
diff --git a/compiler/src/dotty/tools/dotc/core/Constants.scala b/compiler/src/dotty/tools/dotc/core/Constants.scala
index 1892e4bdc..ed388b7ec 100644
--- a/compiler/src/dotty/tools/dotc/core/Constants.scala
+++ b/compiler/src/dotty/tools/dotc/core/Constants.scala
@@ -169,12 +169,12 @@ object Constants {
def convertTo(pt: Type)(implicit ctx: Context): Constant = {
def classBound(pt: Type): Type = pt.dealias.stripTypeVar match {
case tref: TypeRef if !tref.symbol.isClass => classBound(tref.info.bounds.lo)
- case param: PolyParam =>
+ case param: TypeParamRef =>
ctx.typerState.constraint.entry(param) match {
case TypeBounds(lo, hi) =>
if (hi.classSymbol.isPrimitiveValueClass) hi //constrain further with high bound
else classBound(lo)
- case NoType => classBound(param.binder.paramBounds(param.paramNum).lo)
+ case NoType => classBound(param.binder.paramInfos(param.paramNum).lo)
case inst => classBound(inst)
}
case pt => pt
diff --git a/compiler/src/dotty/tools/dotc/core/Constraint.scala b/compiler/src/dotty/tools/dotc/core/Constraint.scala
index 50136a26c..a6c21c0d1 100644
--- a/compiler/src/dotty/tools/dotc/core/Constraint.scala
+++ b/compiler/src/dotty/tools/dotc/core/Constraint.scala
@@ -13,20 +13,20 @@ import config.Printers.constr
/** Constraint over undetermined type parameters. Constraints are built
* over values of the following types:
*
- * - PolyType A constraint constrains the type parameters of a set of PolyTypes
- * - PolyParam The parameters of the constrained polytypes
- * - TypeVar Every constrained parameter might be associated with a TypeVar
- * that has the PolyParam as origin.
+ * - TypeLambda A constraint constrains the type parameters of a set of TypeLambdas
+ * - TypeParamRef The parameters of the constrained type lambdas
+ * - TypeVar Every constrained parameter might be associated with a TypeVar
+ * that has the TypeParamRef as origin.
*/
abstract class Constraint extends Showable {
type This <: Constraint
/** Does the constraint's domain contain the type parameters of `pt`? */
- def contains(pt: PolyType): Boolean
+ def contains(pt: TypeLambda): Boolean
/** Does the constraint's domain contain the type parameter `param`? */
- def contains(param: PolyParam): Boolean
+ def contains(param: TypeParamRef): Boolean
/** Does this constraint contain the type variable `tvar` and is it uninstantiated? */
def contains(tvar: TypeVar): Boolean
@@ -34,43 +34,43 @@ abstract class Constraint extends Showable {
/** The constraint entry for given type parameter `param`, or NoType if `param` is not part of
* the constraint domain. Note: Low level, implementation dependent.
*/
- def entry(param: PolyParam): Type
+ def entry(param: TypeParamRef): Type
/** The type variable corresponding to parameter `param`, or
* NoType, if `param` is not in constrained or is not paired with a type variable.
*/
- def typeVarOfParam(param: PolyParam): Type
+ def typeVarOfParam(param: TypeParamRef): Type
/** Is it known that `param1 <:< param2`? */
- def isLess(param1: PolyParam, param2: PolyParam): Boolean
+ def isLess(param1: TypeParamRef, param2: TypeParamRef): Boolean
/** The parameters that are known to be smaller wrt <: than `param` */
- def lower(param: PolyParam): List[PolyParam]
+ def lower(param: TypeParamRef): List[TypeParamRef]
/** The parameters that are known to be greater wrt <: than `param` */
- def upper(param: PolyParam): List[PolyParam]
+ def upper(param: TypeParamRef): List[TypeParamRef]
/** lower(param) \ lower(butNot) */
- def exclusiveLower(param: PolyParam, butNot: PolyParam): List[PolyParam]
+ def exclusiveLower(param: TypeParamRef, butNot: TypeParamRef): List[TypeParamRef]
/** upper(param) \ upper(butNot) */
- def exclusiveUpper(param: PolyParam, butNot: PolyParam): List[PolyParam]
+ def exclusiveUpper(param: TypeParamRef, butNot: TypeParamRef): List[TypeParamRef]
/** The constraint bounds for given type parameter `param`.
* Poly params that are known to be smaller or greater than `param`
* are not contained in the return bounds.
* @pre `param` is not part of the constraint domain.
*/
- def nonParamBounds(param: PolyParam): TypeBounds
+ def nonParamBounds(param: TypeParamRef): TypeBounds
/** The lower bound of `param` including all known-to-be-smaller parameters */
- def fullLowerBound(param: PolyParam)(implicit ctx: Context): Type
+ def fullLowerBound(param: TypeParamRef)(implicit ctx: Context): Type
/** The upper bound of `param` including all known-to-be-greater parameters */
- def fullUpperBound(param: PolyParam)(implicit ctx: Context): Type
+ def fullUpperBound(param: TypeParamRef)(implicit ctx: Context): Type
/** The bounds of `param` including all known-to-be-smaller and -greater parameters */
- def fullBounds(param: PolyParam)(implicit ctx: Context): TypeBounds
+ def fullBounds(param: TypeParamRef)(implicit ctx: Context): TypeBounds
/** A new constraint which is derived from this constraint by adding
* entries for all type parameters of `poly`.
@@ -79,7 +79,7 @@ abstract class Constraint extends Showable {
* satisfiability but will solved to give instances of
* type variables.
*/
- def add(poly: PolyType, tvars: List[TypeVar])(implicit ctx: Context): This
+ def add(poly: TypeLambda, tvars: List[TypeVar])(implicit ctx: Context): This
/** A new constraint which is derived from this constraint by updating
* the entry for parameter `param` to `tp`.
@@ -90,18 +90,18 @@ abstract class Constraint extends Showable {
*
* @pre `this contains param`.
*/
- def updateEntry(param: PolyParam, tp: Type)(implicit ctx: Context): This
+ def updateEntry(param: TypeParamRef, tp: Type)(implicit ctx: Context): This
/** A constraint that includes the relationship `p1 <: p2`.
* `<:` relationships between parameters ("edges") are propagated, but
* non-parameter bounds are left alone.
*/
- def addLess(p1: PolyParam, p2: PolyParam)(implicit ctx: Context): This
+ def addLess(p1: TypeParamRef, p2: TypeParamRef)(implicit ctx: Context): This
/** A constraint resulting from adding p2 = p1 to this constraint, and at the same
* time transferring all bounds of p2 to p1
*/
- def unify(p1: PolyParam, p2: PolyParam)(implicit ctx: Context): This
+ def unify(p1: TypeParamRef, p2: TypeParamRef)(implicit ctx: Context): This
/** A new constraint which is derived from this constraint by removing
* the type parameter `param` from the domain and replacing all top-level occurrences
@@ -109,25 +109,25 @@ abstract class Constraint extends Showable {
* approximation of it if that is needed to avoid cycles.
* Occurrences nested inside a refinement or prefix are not affected.
*/
- def replace(param: PolyParam, tp: Type)(implicit ctx: Context): This
+ def replace(param: TypeParamRef, tp: Type)(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.
*/
- def isRemovable(pt: PolyType): Boolean
+ def isRemovable(pt: TypeLambda): Boolean
/** A new constraint with all entries coming from `pt` removed. */
- def remove(pt: PolyType)(implicit ctx: Context): This
+ def remove(pt: TypeLambda)(implicit ctx: Context): This
- /** The polytypes constrained by this constraint */
- def domainPolys: List[PolyType]
+ /** The type lambdas constrained by this constraint */
+ def domainLambdas: List[TypeLambda]
- /** The polytype parameters constrained by this constraint */
- def domainParams: List[PolyParam]
+ /** The type lambda parameters constrained by this constraint */
+ def domainParams: List[TypeParamRef]
/** Check whether predicate holds for all parameters in constraint */
- def forallParams(p: PolyParam => Boolean): Boolean
+ def forallParams(p: TypeParamRef => Boolean): Boolean
/** Perform operation `op` on all typevars, or only on uninstantiated
* typevars, depending on whether `uninstOnly` is set or not.
@@ -143,6 +143,6 @@ abstract class Constraint extends Showable {
/** Check that no constrained parameter contains itself as a bound */
def checkNonCyclic()(implicit ctx: Context): Unit
- /** Check that constraint only refers to PolyParams bound by itself */
+ /** Check that constraint only refers to TypeParamRefs bound by itself */
def checkClosed()(implicit ctx: Context): Unit
}
diff --git a/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala b/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala
index a12936c58..de96f644a 100644
--- a/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala
+++ b/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala
@@ -42,12 +42,12 @@ trait ConstraintHandling {
*/
protected var homogenizeArgs = false
- /** We are currently comparing polytypes. Used as a flag for
+ /** We are currently comparing type lambdas. Used as a flag for
* optimization: when `false`, no need to do an expensive `pruneLambdaParams`
*/
- protected var comparedPolyTypes: Set[PolyType] = Set.empty
+ protected var comparedTypeLambdas: Set[TypeLambda] = Set.empty
- private def addOneBound(param: PolyParam, bound: Type, isUpper: Boolean): Boolean =
+ private def addOneBound(param: TypeParamRef, bound: Type, isUpper: Boolean): Boolean =
!constraint.contains(param) || {
def occursIn(bound: Type): Boolean = {
val b = bound.dealias
@@ -75,7 +75,7 @@ trait ConstraintHandling {
* 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 = {
+ def narrowedBound(param: TypeParamRef, bound: Type, isUpper: Boolean)(implicit ctx: Context): TypeBounds = {
val oldBounds @ TypeBounds(lo, hi) = constraint.nonParamBounds(param)
val saved = homogenizeArgs
homogenizeArgs = Config.alignArgsInAnd
@@ -85,7 +85,7 @@ trait ConstraintHandling {
finally homogenizeArgs = saved
}
- protected def addUpperBound(param: PolyParam, bound: Type): Boolean = {
+ protected def addUpperBound(param: TypeParamRef, bound: Type): Boolean = {
def description = i"constraint $param <: $bound to\n$constraint"
if (bound.isRef(defn.NothingClass) && ctx.typerState.isGlobalCommittable) {
def msg = s"!!! instantiated to Nothing: $param, constraint = ${constraint.show}"
@@ -101,7 +101,7 @@ trait ConstraintHandling {
res
}
- protected def addLowerBound(param: PolyParam, bound: Type): Boolean = {
+ protected def addLowerBound(param: TypeParamRef, bound: Type): Boolean = {
def description = i"constraint $param >: $bound to\n$constraint"
constr.println(i"adding $description")
val upper = constraint.upper(param)
@@ -112,7 +112,7 @@ trait ConstraintHandling {
res
}
- protected def addLess(p1: PolyParam, p2: PolyParam): Boolean = {
+ protected def addLess(p1: TypeParamRef, p2: TypeParamRef): Boolean = {
def description = i"ordering $p1 <: $p2 to\n$constraint"
val res =
if (constraint.isLess(p2, p1)) unify(p2, p1)
@@ -133,7 +133,7 @@ trait ConstraintHandling {
/** Make p2 = p1, transfer all bounds of p2 to p1
* @pre less(p1)(p2)
*/
- private def unify(p1: PolyParam, p2: PolyParam): Boolean = {
+ private def unify(p1: TypeParamRef, p2: TypeParamRef): Boolean = {
constr.println(s"unifying $p1 $p2")
assert(constraint.isLess(p1, p2))
val down = constraint.exclusiveLower(p2, p1)
@@ -191,7 +191,7 @@ trait ConstraintHandling {
* @return the instantiating type
* @pre `param` is in the constraint's domain.
*/
- final def approximation(param: PolyParam, fromBelow: Boolean): Type = {
+ final def approximation(param: TypeParamRef, fromBelow: Boolean): Type = {
val avoidParam = new TypeMap {
override def stopAtStatic = true
def apply(tp: Type) = mapOver {
@@ -235,7 +235,7 @@ trait ConstraintHandling {
* a lower bound instantiation can be a singleton type only if the upper bound
* is also a singleton type.
*/
- def instanceType(param: PolyParam, fromBelow: Boolean): Type = {
+ def instanceType(param: TypeParamRef, fromBelow: Boolean): Type = {
def upperBound = constraint.fullUpperBound(param)
def isSingleton(tp: Type): Boolean = tp match {
case tp: SingletonType => true
@@ -301,26 +301,26 @@ trait ConstraintHandling {
}
/** The current bounds of type parameter `param` */
- final def bounds(param: PolyParam): TypeBounds = {
+ final def bounds(param: TypeParamRef): TypeBounds = {
val e = constraint.entry(param)
- if (e.exists) e.bounds else param.binder.paramBounds(param.paramNum)
+ if (e.exists) e.bounds else param.binder.paramInfos(param.paramNum)
}
- /** Add polytype `pt`, possibly with type variables `tvars`, to current constraint
+ /** Add type lambda `tl`, possibly with type variables `tvars`, to current constraint
* and propagate all bounds.
* @param tvars See Constraint#add
*/
- def addToConstraint(pt: PolyType, tvars: List[TypeVar]): Unit =
+ def addToConstraint(tl: TypeLambda, tvars: List[TypeVar]): Unit =
assert {
- checkPropagated(i"initialized $pt") {
- constraint = constraint.add(pt, tvars)
- pt.paramNames.indices.forall { i =>
- val param = PolyParam(pt, i)
+ checkPropagated(i"initialized $tl") {
+ constraint = constraint.add(tl, tvars)
+ tl.paramNames.indices.forall { i =>
+ val param = TypeParamRef(tl, i)
val bounds = constraint.nonParamBounds(param)
val lower = constraint.lower(param)
val upper = constraint.upper(param)
if (lower.nonEmpty && !bounds.lo.isRef(defn.NothingClass) ||
- upper.nonEmpty && !bounds.hi.isRef(defn.AnyClass)) constr.println(i"INIT*** $pt")
+ upper.nonEmpty && !bounds.hi.isRef(defn.AnyClass)) constr.println(i"INIT*** $tl")
lower.forall(addOneBound(_, bounds.hi, isUpper = true)) &&
upper.forall(addOneBound(_, bounds.lo, isUpper = false))
}
@@ -328,7 +328,7 @@ trait ConstraintHandling {
}
/** Can `param` be constrained with new bounds? */
- final def canConstrain(param: PolyParam): Boolean =
+ final def canConstrain(param: TypeParamRef): Boolean =
!frozenConstraint && (constraint contains param)
/** Add constraint `param <: bound` if `fromBelow` is false, `param >: bound` otherwise.
@@ -338,7 +338,7 @@ trait ConstraintHandling {
* not be AndTypes and lower bounds may not be OrTypes. This is assured by the
* way isSubType is organized.
*/
- protected def addConstraint(param: PolyParam, bound: Type, fromBelow: Boolean): Boolean = {
+ protected def addConstraint(param: TypeParamRef, bound: Type, fromBelow: Boolean): Boolean = {
def description = i"constr $param ${if (fromBelow) ">:" else "<:"} $bound:\n$constraint"
//checkPropagated(s"adding $description")(true) // DEBUG in case following fails
checkPropagated(s"added $description") {
@@ -357,12 +357,12 @@ trait ConstraintHandling {
* missing.
*/
def pruneLambdaParams(tp: Type) =
- if (comparedPolyTypes.nonEmpty) {
+ if (comparedTypeLambdas.nonEmpty) {
val approx = new ApproximatingTypeMap {
def apply(t: Type): Type = t match {
- case t @ PolyParam(pt: PolyType, n) if comparedPolyTypes contains pt =>
+ case t @ TypeParamRef(tl: TypeLambda, n) if comparedTypeLambdas contains tl =>
val effectiveVariance = if (fromBelow) -variance else variance
- val bounds = pt.paramBounds(n)
+ val bounds = tl.paramInfos(n)
if (effectiveVariance > 0) bounds.lo
else if (effectiveVariance < 0) bounds.hi
else NoType
@@ -374,7 +374,7 @@ trait ConstraintHandling {
}
else tp
- def addParamBound(bound: PolyParam) =
+ def addParamBound(bound: TypeParamRef) =
if (fromBelow) addLess(bound, param) else addLess(param, bound)
/** Drop all constrained parameters that occur at the toplevel in `bound` and
@@ -419,7 +419,7 @@ trait ConstraintHandling {
else NoType
case bound: TypeVar if constraint contains bound.origin =>
prune(bound.underlying)
- case bound: PolyParam =>
+ case bound: TypeParamRef =>
constraint.entry(bound) match {
case NoType => pruneLambdaParams(bound)
case _: TypeBounds =>
@@ -434,7 +434,7 @@ trait ConstraintHandling {
}
try bound match {
- case bound: PolyParam if constraint contains bound =>
+ case bound: TypeParamRef if constraint contains bound =>
addParamBound(bound)
case _ =>
val pbound = prune(bound)
@@ -446,7 +446,7 @@ trait ConstraintHandling {
}
/** Instantiate `param` to `tp` if the constraint stays satisfiable */
- protected def tryInstantiate(param: PolyParam, tp: Type): Boolean = {
+ protected def tryInstantiate(param: TypeParamRef, tp: Type): Boolean = {
val saved = constraint
constraint =
if (addConstraint(param, tp, fromBelow = true) &&
@@ -461,7 +461,7 @@ trait ConstraintHandling {
val saved = frozenConstraint
frozenConstraint = true
for (p <- constraint.domainParams) {
- def check(cond: => Boolean, q: PolyParam, ordering: String, explanation: String): Unit =
+ def check(cond: => Boolean, q: TypeParamRef, ordering: String, explanation: String): Unit =
assert(cond, i"propagation failure for $p $ordering $q: $explanation\n$msg")
for (u <- constraint.upper(p))
check(bounds(p).hi <:< bounds(u).hi, u, "<:", "upper bound not propagated")
diff --git a/compiler/src/dotty/tools/dotc/core/Contexts.scala b/compiler/src/dotty/tools/dotc/core/Contexts.scala
index 6b7be12be..8707b66f9 100644
--- a/compiler/src/dotty/tools/dotc/core/Contexts.scala
+++ b/compiler/src/dotty/tools/dotc/core/Contexts.scala
@@ -306,13 +306,14 @@ object Contexts {
sb.append(str)
}
- /** The next outer context whose tree is a template or package definition */
+ /** The next outer context whose tree is a template or package definition
+ * Note: Currently unused
def enclTemplate: Context = {
var c = this
while (c != NoContext && !c.tree.isInstanceOf[Template[_]] && !c.tree.isInstanceOf[PackageDef[_]])
c = c.outer
c
- }
+ }*/
/** The context for a supercall. This context is used for elaborating
* the parents of a class and their arguments.
diff --git a/compiler/src/dotty/tools/dotc/core/Decorators.scala b/compiler/src/dotty/tools/dotc/core/Decorators.scala
index 0e8ae196a..c65dc5b97 100644
--- a/compiler/src/dotty/tools/dotc/core/Decorators.scala
+++ b/compiler/src/dotty/tools/dotc/core/Decorators.scala
@@ -185,7 +185,7 @@ object Decorators {
* give more info about type variables and to disambiguate where needed.
*/
def ex(args: Any*)(implicit ctx: Context): String =
- explained2(implicit ctx => em(args: _*))
+ explained(implicit ctx => em(args: _*))
/** Formatter that adds syntax highlighting to all interpolated values */
def hl(args: Any*)(implicit ctx: Context): String =
diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala
index 4d4350f98..b70fcb093 100644
--- a/compiler/src/dotty/tools/dotc/core/Definitions.scala
+++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala
@@ -150,9 +150,9 @@ class Definitions {
private def enterPolyMethod(cls: ClassSymbol, name: TermName, typeParamCount: Int,
resultTypeFn: PolyType => Type, flags: FlagSet = EmptyFlags) = {
- val tparamNames = tpnme.syntheticTypeParamNames(typeParamCount)
- val tparamBounds = tparamNames map (_ => TypeBounds.empty)
- val ptype = PolyType(tparamNames, tparamNames.map(alwaysZero))(_ => tparamBounds, resultTypeFn)
+ val tparamNames = PolyType.syntheticParamNames(typeParamCount)
+ val tparamInfos = tparamNames map (_ => TypeBounds.empty)
+ val ptype = PolyType(tparamNames)(_ => tparamInfos, resultTypeFn)
enterMethod(cls, name, ptype, flags)
}
@@ -242,7 +242,7 @@ class Definitions {
lazy val Any_## = enterMethod(AnyClass, nme.HASHHASH, ExprType(IntType), Final)
lazy val Any_getClass = enterMethod(AnyClass, nme.getClass_, MethodType(Nil, ClassClass.typeRef.appliedTo(TypeBounds.empty)), Final)
lazy val Any_isInstanceOf = enterT1ParameterlessMethod(AnyClass, nme.isInstanceOf_, _ => BooleanType, Final)
- lazy val Any_asInstanceOf = enterT1ParameterlessMethod(AnyClass, nme.asInstanceOf_, PolyParam(_, 0), Final)
+ lazy val Any_asInstanceOf = enterT1ParameterlessMethod(AnyClass, nme.asInstanceOf_, TypeParamRef(_, 0), Final)
def AnyMethods = List(Any_==, Any_!=, Any_equals, Any_hashCode,
Any_toString, Any_##, Any_getClass, Any_isInstanceOf, Any_asInstanceOf)
@@ -268,7 +268,7 @@ class Definitions {
lazy val Object_eq = enterMethod(ObjectClass, nme.eq, methOfAnyRef(BooleanType), Final)
lazy val Object_ne = enterMethod(ObjectClass, nme.ne, methOfAnyRef(BooleanType), Final)
lazy val Object_synchronized = enterPolyMethod(ObjectClass, nme.synchronized_, 1,
- pt => MethodType(List(PolyParam(pt, 0)), PolyParam(pt, 0)), Final)
+ pt => MethodType(List(TypeParamRef(pt, 0)), TypeParamRef(pt, 0)), Final)
lazy val Object_clone = enterMethod(ObjectClass, nme.clone_, MethodType(Nil, ObjectType), Protected)
lazy val Object_finalize = enterMethod(ObjectClass, nme.finalize_, MethodType(Nil, UnitType), Protected)
lazy val Object_notify = enterMethod(ObjectClass, nme.notify_, MethodType(Nil, UnitType))
@@ -283,7 +283,7 @@ class Definitions {
/** Dummy method needed by elimByName */
lazy val dummyApply = enterPolyMethod(
OpsPackageClass, nme.dummyApply, 1,
- pt => MethodType(List(FunctionOf(Nil, PolyParam(pt, 0))), PolyParam(pt, 0)))
+ pt => MethodType(List(FunctionOf(Nil, TypeParamRef(pt, 0))), TypeParamRef(pt, 0)))
/** Method representing a throw */
lazy val throwMethod = enterMethod(OpsPackageClass, nme.THROWkw,
@@ -512,6 +512,10 @@ class Definitions {
def DynamicClass(implicit ctx: Context) = DynamicType.symbol.asClass
lazy val OptionType: TypeRef = ctx.requiredClassRef("scala.Option")
def OptionClass(implicit ctx: Context) = OptionType.symbol.asClass
+ lazy val EnumType: TypeRef = ctx.requiredClassRef("scala.Enum")
+ def EnumClass(implicit ctx: Context) = EnumType.symbol.asClass
+ lazy val EnumValuesType: TypeRef = ctx.requiredClassRef("scala.runtime.EnumValues")
+ def EnumValuesClass(implicit ctx: Context) = EnumValuesType.symbol.asClass
lazy val ProductType: TypeRef = ctx.requiredClassRef("scala.Product")
def ProductClass(implicit ctx: Context) = ProductType.symbol.asClass
lazy val Product_canEqualR = ProductClass.requiredMethodRef(nme.canEqual_)
diff --git a/compiler/src/dotty/tools/dotc/core/Denotations.scala b/compiler/src/dotty/tools/dotc/core/Denotations.scala
index f726cd0d1..7341b96af 100644
--- a/compiler/src/dotty/tools/dotc/core/Denotations.scala
+++ b/compiler/src/dotty/tools/dotc/core/Denotations.scala
@@ -213,7 +213,7 @@ object Denotations {
def requiredMethod(name: PreName, argTypes: List[Type])(implicit ctx: Context): TermSymbol =
info.member(name.toTermName).requiredSymbol(x=>
- (x is Method) && x.info.paramTypess == List(argTypes)
+ (x is Method) && x.info.paramInfoss == List(argTypes)
).asTerm
def requiredMethodRef(name: PreName, argTypes: List[Type])(implicit ctx: Context): TermRef =
requiredMethod(name, argTypes).termRef
@@ -252,13 +252,12 @@ object Denotations {
else throw new Error(s"cannot merge ${showType(tp1)} with ${showType(tp2)}") // flip condition for debugging
}
- /** Merge two lists of names. If names in corresponding positions match, keep them,
+ /** Merge parameter names of lambda types. If names in corresponding positions match, keep them,
* otherwise generate new synthetic names.
*/
- def mergeNames[N <: Name](names1: List[N], names2: List[N], syntheticName: Int => N): List[N] = {
- for ((name1, name2, idx) <- (names1, names2, 0 until names1.length).zipped)
- yield if (name1 == name2) name1 else syntheticName(idx)
- }.toList
+ private def mergeParamNames(tp1: LambdaType, tp2: LambdaType): List[tp1.ThisName] =
+ (for ((name1, name2, idx) <- (tp1.paramNames, tp2.paramNames, tp1.paramNames.indices).zipped)
+ yield if (name1 == name2) name1 else tp1.companion.syntheticParamName(idx)).toList
/** Form a denotation by conjoining with denotation `that`.
*
@@ -308,27 +307,17 @@ object Denotations {
case tp2: TypeBounds if tp2 contains tp1 => tp1
case _ => mergeConflict(tp1, tp2)
}
- case tp1: MethodType if isTerm =>
+ case tp1: MethodOrPoly =>
tp2 match {
- case tp2: MethodType if ctx.typeComparer.matchingParams(tp1.paramTypes, tp2.paramTypes, tp1.isJava, tp2.isJava) &&
- tp1.isImplicit == tp2.isImplicit =>
- tp1.derivedMethodType(
- mergeNames(tp1.paramNames, tp2.paramNames, nme.syntheticParamName),
- tp1.paramTypes,
+ case tp2: MethodOrPoly
+ if ctx.typeComparer.matchingParams(tp1, tp2) &&
+ tp1.isImplicit == tp2.isImplicit =>
+ tp1.derivedLambdaType(
+ mergeParamNames(tp1, tp2), tp1.paramInfos,
infoMeet(tp1.resultType, tp2.resultType.subst(tp2, tp1)))
case _ =>
mergeConflict(tp1, tp2)
}
- case tp1: PolyType if isTerm =>
- tp2 match {
- case tp2: PolyType if ctx.typeComparer.matchingTypeParams(tp1, tp2) =>
- tp1.derivedPolyType(
- mergeNames(tp1.paramNames, tp2.paramNames, tpnme.syntheticTypeParamName),
- tp1.paramBounds,
- infoMeet(tp1.resultType, tp2.resultType.subst(tp2, tp1)))
- case _: MethodicType =>
- mergeConflict(tp1, tp2)
- }
case _ =>
tp1 & tp2
}
@@ -471,23 +460,14 @@ object Denotations {
case tp2: TypeBounds if tp2 contains tp1 => tp2
case _ => mergeConflict(tp1, tp2)
}
- case tp1: MethodType =>
- tp2 match {
- case tp2: MethodType
- if ctx.typeComparer.matchingParams(tp1.paramTypes, tp2.paramTypes, tp1.isJava, tp2.isJava) &&
- tp1.isImplicit == tp2.isImplicit =>
- tp1.derivedMethodType(
- mergeNames(tp1.paramNames, tp2.paramNames, nme.syntheticParamName),
- tp1.paramTypes, tp1.resultType | tp2.resultType.subst(tp2, tp1))
- case _ =>
- mergeConflict(tp1, tp2)
- }
- case tp1: PolyType =>
+ case tp1: MethodOrPoly =>
tp2 match {
- case tp2: PolyType if ctx.typeComparer.matchingTypeParams(tp1, tp2) =>
- tp1.derivedPolyType(
- mergeNames(tp1.paramNames, tp2.paramNames, tpnme.syntheticTypeParamName),
- tp1.paramBounds, tp1.resultType | tp2.resultType.subst(tp2, tp1))
+ case tp2: MethodOrPoly
+ if ctx.typeComparer.matchingParams(tp1, tp2) &&
+ tp1.isImplicit == tp2.isImplicit =>
+ tp1.derivedLambdaType(
+ mergeParamNames(tp1, tp2), tp1.paramInfos,
+ 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 c1267d8a2..29f1078a2 100644
--- a/compiler/src/dotty/tools/dotc/core/Flags.scala
+++ b/compiler/src/dotty/tools/dotc/core/Flags.scala
@@ -450,13 +450,22 @@ object Flags {
/** Flags guaranteed to be set upon symbol creation */
final val FromStartFlags =
- AccessFlags | Module | Package | Deferred | Final | MethodOrHKCommon | Param | ParamAccessor | Scala2ExistentialCommon |
- Mutable.toCommonFlags | InSuperCall | Touched | JavaStatic | CovariantOrOuter | ContravariantOrLabel | ExpandedName | AccessorOrSealed |
- CaseAccessorOrBaseTypeArg | Fresh | Frozen | Erroneous | ImplicitCommon | Permanent | Synthetic |
- Inline | LazyOrTrait | SuperAccessorOrScala2x | SelfNameOrImplClass
+ Module | Package | Deferred | MethodOrHKCommon | Param | ParamAccessor |
+ Scala2ExistentialCommon | Mutable.toCommonFlags | InSuperCall | Touched | JavaStatic |
+ CovariantOrOuter | ContravariantOrLabel | ExpandedName | CaseAccessorOrBaseTypeArg |
+ Fresh | Frozen | Erroneous | ImplicitCommon | Permanent | Synthetic |
+ SuperAccessorOrScala2x | Inline
+
+ /** Flags guaranteed to be set upon symbol creation, or, if symbol is a top-level
+ * class or object, when the class file defining the symbol is loaded (which
+ * is generally before the symbol is completed
+ */
+ final val AfterLoadFlags =
+ FromStartFlags | AccessFlags | Final | AccessorOrSealed | LazyOrTrait | SelfNameOrImplClass
assert(FromStartFlags.isTermFlags && FromStartFlags.isTypeFlags)
// TODO: Should check that FromStartFlags do not change in completion
+ assert(AfterLoadFlags.isTermFlags && AfterLoadFlags.isTypeFlags)
/** A value that's unstable unless complemented with a Stable flag */
final val UnstableValue = Mutable | Method
diff --git a/compiler/src/dotty/tools/dotc/core/Mode.scala b/compiler/src/dotty/tools/dotc/core/Mode.scala
index 406a84af6..c835f677e 100644
--- a/compiler/src/dotty/tools/dotc/core/Mode.scala
+++ b/compiler/src/dotty/tools/dotc/core/Mode.scala
@@ -34,7 +34,7 @@ object Mode {
* context with typerstate and constraint. This is typically done when we
* cache the eligibility of implicits. Caching needs to be done across different constraints.
* Therefore, if TypevarsMissContext is set, subtyping becomes looser, and assumes
- * that PolyParams can be sub- and supertypes of anything. See TypeComparer.
+ * that TypeParamRefs can be sub- and supertypes of anything. See TypeComparer.
*/
val TypevarsMissContext = newMode(4, "TypevarsMissContext")
val CheckCyclic = newMode(5, "CheckCyclic")
diff --git a/compiler/src/dotty/tools/dotc/core/NameOps.scala b/compiler/src/dotty/tools/dotc/core/NameOps.scala
index ea905c19f..240ad359b 100644
--- a/compiler/src/dotty/tools/dotc/core/NameOps.scala
+++ b/compiler/src/dotty/tools/dotc/core/NameOps.scala
@@ -196,6 +196,31 @@ object NameOps {
if (name.isModuleClassName) name.stripModuleClassSuffix.freshened.moduleClassName
else likeTyped(ctx.freshName(name ++ NameTransformer.NAME_JOIN_STRING)))
+ /** Name with variance prefix: `+` for covariant, `-` for contravariant */
+ def withVariance(v: Int): N =
+ if (hasVariance) dropVariance.withVariance(v)
+ else v match {
+ case -1 => likeTyped('-' +: name)
+ case 1 => likeTyped('+' +: name)
+ case 0 => name
+ }
+
+ /** Does name have a `+`/`-` variance prefix? */
+ def hasVariance: Boolean =
+ name.nonEmpty && name.head == '+' || name.head == '-'
+
+ /** Drop variance prefix if name has one */
+ def dropVariance: N = if (hasVariance) likeTyped(name.tail) else name
+
+ /** The variance as implied by the variance prefix, or 0 if there is
+ * no variance prefix.
+ */
+ def variance = name.head match {
+ case '-' => -1
+ case '+' => 1
+ case _ => 0
+ }
+
/** Translate a name into a list of simple TypeNames and TermNames.
* In all segments before the last, type/term is determined by whether
* the following separator char is '.' or '#'. The last segment
@@ -271,7 +296,6 @@ object NameOps {
else -1
}
-
/** The number of hops specified in an outer-select name */
def outerSelectHops: Int = {
require(isOuterSelect)
diff --git a/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala b/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala
index 61dd5a445..84b0bfc6d 100644
--- a/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala
+++ b/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala
@@ -14,13 +14,13 @@ import annotation.tailrec
object OrderingConstraint {
- type ArrayValuedMap[T] = SimpleMap[PolyType, Array[T]]
+ type ArrayValuedMap[T] = SimpleMap[TypeLambda, Array[T]]
/** The type of `OrderingConstraint#boundsMap` */
type ParamBounds = ArrayValuedMap[Type]
/** The type of `OrderingConstraint#lowerMap`, `OrderingConstraint#upperMap` */
- type ParamOrdering = ArrayValuedMap[List[PolyParam]]
+ type ParamOrdering = ArrayValuedMap[List[TypeParamRef]]
/** A new constraint with given maps */
private def newConstraint(boundsMap: ParamBounds, lowerMap: ParamOrdering, upperMap: ParamOrdering)(implicit ctx: Context) : OrderingConstraint = {
@@ -32,11 +32,11 @@ object OrderingConstraint {
/** A lens for updating a single entry array in one of the three constraint maps */
abstract class ConstraintLens[T <: AnyRef: ClassTag] {
- def entries(c: OrderingConstraint, poly: PolyType): Array[T]
- def updateEntries(c: OrderingConstraint, poly: PolyType, entries: Array[T])(implicit ctx: Context): OrderingConstraint
+ def entries(c: OrderingConstraint, poly: TypeLambda): Array[T]
+ def updateEntries(c: OrderingConstraint, poly: TypeLambda, entries: Array[T])(implicit ctx: Context): OrderingConstraint
def initial: T
- def apply(c: OrderingConstraint, poly: PolyType, idx: Int) = {
+ def apply(c: OrderingConstraint, poly: TypeLambda, idx: Int) = {
val es = entries(c, poly)
if (es == null) initial else es(idx)
}
@@ -47,7 +47,7 @@ object OrderingConstraint {
* parts of `current` which are not shared by `prev`.
*/
def update(prev: OrderingConstraint, current: OrderingConstraint,
- poly: PolyType, idx: Int, entry: T)(implicit ctx: Context): OrderingConstraint = {
+ poly: TypeLambda, idx: Int, entry: T)(implicit ctx: Context): OrderingConstraint = {
var es = entries(current, poly)
if (es != null && (es(idx) eq entry)) current
else {
@@ -68,38 +68,38 @@ object OrderingConstraint {
}
def update(prev: OrderingConstraint, current: OrderingConstraint,
- param: PolyParam, entry: T)(implicit ctx: Context): OrderingConstraint =
+ param: TypeParamRef, entry: T)(implicit ctx: Context): OrderingConstraint =
update(prev, current, param.binder, param.paramNum, entry)
def map(prev: OrderingConstraint, current: OrderingConstraint,
- poly: PolyType, idx: Int, f: T => T)(implicit ctx: Context): OrderingConstraint =
+ poly: TypeLambda, idx: Int, f: T => T)(implicit ctx: Context): OrderingConstraint =
update(prev, current, poly, idx, f(apply(current, poly, idx)))
def map(prev: OrderingConstraint, current: OrderingConstraint,
- param: PolyParam, f: T => T)(implicit ctx: Context): OrderingConstraint =
+ param: TypeParamRef, f: T => T)(implicit ctx: Context): OrderingConstraint =
map(prev, current, param.binder, param.paramNum, f)
}
val boundsLens = new ConstraintLens[Type] {
- def entries(c: OrderingConstraint, poly: PolyType): Array[Type] =
+ def entries(c: OrderingConstraint, poly: TypeLambda): Array[Type] =
c.boundsMap(poly)
- def updateEntries(c: OrderingConstraint, poly: PolyType, entries: Array[Type])(implicit ctx: Context): OrderingConstraint =
+ def updateEntries(c: OrderingConstraint, poly: TypeLambda, entries: Array[Type])(implicit ctx: Context): OrderingConstraint =
newConstraint(c.boundsMap.updated(poly, entries), c.lowerMap, c.upperMap)
def initial = NoType
}
- val lowerLens = new ConstraintLens[List[PolyParam]] {
- def entries(c: OrderingConstraint, poly: PolyType): Array[List[PolyParam]] =
+ val lowerLens = new ConstraintLens[List[TypeParamRef]] {
+ def entries(c: OrderingConstraint, poly: TypeLambda): Array[List[TypeParamRef]] =
c.lowerMap(poly)
- def updateEntries(c: OrderingConstraint, poly: PolyType, entries: Array[List[PolyParam]])(implicit ctx: Context): OrderingConstraint =
+ def updateEntries(c: OrderingConstraint, poly: TypeLambda, entries: Array[List[TypeParamRef]])(implicit ctx: Context): OrderingConstraint =
newConstraint(c.boundsMap, c.lowerMap.updated(poly, entries), c.upperMap)
def initial = Nil
}
- val upperLens = new ConstraintLens[List[PolyParam]] {
- def entries(c: OrderingConstraint, poly: PolyType): Array[List[PolyParam]] =
+ val upperLens = new ConstraintLens[List[TypeParamRef]] {
+ def entries(c: OrderingConstraint, poly: TypeLambda): Array[List[TypeParamRef]] =
c.upperMap(poly)
- def updateEntries(c: OrderingConstraint, poly: PolyType, entries: Array[List[PolyParam]])(implicit ctx: Context): OrderingConstraint =
+ def updateEntries(c: OrderingConstraint, poly: TypeLambda, entries: Array[List[TypeParamRef]])(implicit ctx: Context): OrderingConstraint =
newConstraint(c.boundsMap, c.lowerMap, c.upperMap.updated(poly, entries))
def initial = Nil
}
@@ -109,20 +109,20 @@ import OrderingConstraint._
/** Constraint over undetermined type parameters that keeps separate maps to
* reflect parameter orderings.
- * @param boundsMap a map from PolyType to arrays.
+ * @param boundsMap a map from TypeLambda to arrays.
* Each array contains twice the number of entries as there a type parameters
- * in the PolyType. The first half of the array contains the type bounds that constrain the
- * polytype's type parameters. The second half might contain type variables that
+ * in the TypeLambda. The first half of the array contains the type bounds that constrain the
+ * lambda's type parameters. The second half might contain type variables that
* track the corresponding parameters, or is left empty (filled with nulls).
* An instantiated type parameter is represented by having its instance type in
* the corresponding array entry. The dual use of arrays for poly params
* and typevars is to save space and hopefully gain some speed.
*
- * @param lowerMap a map from PolyTypes to arrays. Each array entry corresponds
- * to a parameter P of the polytype; it contains all constrained parameters
+ * @param lowerMap a map from TypeLambdas to arrays. Each array entry corresponds
+ * to a parameter P of the type lambda; it contains all constrained parameters
* Q that are known to be smaller than P, i.e. Q <: P.
- * @param upperMap a map from PolyTypes to arrays. Each array entry corresponds
- * to a parameter P of the polytype; it contains all constrained parameters
+ * @param upperMap a map from TypeLambdas to arrays. Each array entry corresponds
+ * to a parameter P of the type lambda; it contains all constrained parameters
* Q that are known to be greater than P, i.e. P <: Q.
*/
class OrderingConstraint(private val boundsMap: ParamBounds,
@@ -141,7 +141,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
entries(paramCount(entries) + n)
/** The `boundsMap` entry corresponding to `param` */
- def entry(param: PolyParam): Type = {
+ def entry(param: TypeParamRef): Type = {
val entries = boundsMap(param.binder)
if (entries == null) NoType
else entries(param.paramNum)
@@ -149,9 +149,9 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
// ----------- Contains tests --------------------------------------------------
- def contains(pt: PolyType): Boolean = boundsMap(pt) != null
+ def contains(pt: TypeLambda): Boolean = boundsMap(pt) != null
- def contains(param: PolyParam): Boolean = {
+ def contains(param: TypeParamRef): Boolean = {
val entries = boundsMap(param.binder)
entries != null && isBounds(entries(param.paramNum))
}
@@ -167,43 +167,43 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
// ---------- Dependency handling ----------------------------------------------
- def lower(param: PolyParam): List[PolyParam] = lowerLens(this, param.binder, param.paramNum)
- def upper(param: PolyParam): List[PolyParam] = upperLens(this, param.binder, param.paramNum)
+ def lower(param: TypeParamRef): List[TypeParamRef] = lowerLens(this, param.binder, param.paramNum)
+ def upper(param: TypeParamRef): List[TypeParamRef] = upperLens(this, param.binder, param.paramNum)
- def minLower(param: PolyParam): List[PolyParam] = {
+ def minLower(param: TypeParamRef): List[TypeParamRef] = {
val all = lower(param)
all.filterNot(p => all.exists(isLess(p, _)))
}
- def minUpper(param: PolyParam): List[PolyParam] = {
+ def minUpper(param: TypeParamRef): List[TypeParamRef] = {
val all = upper(param)
all.filterNot(p => all.exists(isLess(_, p)))
}
- def exclusiveLower(param: PolyParam, butNot: PolyParam): List[PolyParam] =
+ def exclusiveLower(param: TypeParamRef, butNot: TypeParamRef): List[TypeParamRef] =
lower(param).filterNot(isLess(_, butNot))
- def exclusiveUpper(param: PolyParam, butNot: PolyParam): List[PolyParam] =
+ def exclusiveUpper(param: TypeParamRef, butNot: TypeParamRef): List[TypeParamRef] =
upper(param).filterNot(isLess(butNot, _))
-// ---------- Info related to PolyParams -------------------------------------------
+// ---------- Info related to TypeParamRefs -------------------------------------------
- def isLess(param1: PolyParam, param2: PolyParam): Boolean =
+ def isLess(param1: TypeParamRef, param2: TypeParamRef): Boolean =
upper(param1).contains(param2)
- def nonParamBounds(param: PolyParam): TypeBounds =
+ def nonParamBounds(param: TypeParamRef): TypeBounds =
entry(param).asInstanceOf[TypeBounds]
- def fullLowerBound(param: PolyParam)(implicit ctx: Context): Type =
+ def fullLowerBound(param: TypeParamRef)(implicit ctx: Context): Type =
(nonParamBounds(param).lo /: minLower(param))(_ | _)
- def fullUpperBound(param: PolyParam)(implicit ctx: Context): Type =
+ def fullUpperBound(param: TypeParamRef)(implicit ctx: Context): Type =
(nonParamBounds(param).hi /: minUpper(param))(_ & _)
- def fullBounds(param: PolyParam)(implicit ctx: Context): TypeBounds =
+ def fullBounds(param: TypeParamRef)(implicit ctx: Context): TypeBounds =
nonParamBounds(param).derivedTypeBounds(fullLowerBound(param), fullUpperBound(param))
- def typeVarOfParam(param: PolyParam): Type = {
+ def typeVarOfParam(param: TypeParamRef): Type = {
val entries = boundsMap(param.binder)
if (entries == null) NoType
else {
@@ -212,15 +212,15 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
}
}
-// ---------- Adding PolyTypes --------------------------------------------------
+// ---------- Adding TypeLambdas --------------------------------------------------
/** The list of parameters P such that, for a fresh type parameter Q:
*
* Q <: tp implies Q <: P and isUpper = true, or
* tp <: Q implies P <: Q and isUpper = false
*/
- def dependentParams(tp: Type, isUpper: Boolean): List[PolyParam] = tp match {
- case param: PolyParam if contains(param) =>
+ def dependentParams(tp: Type, isUpper: Boolean): List[TypeParamRef] = tp match {
+ case param: TypeParamRef if contains(param) =>
param :: (if (isUpper) upper(param) else lower(param))
case tp: AndOrType =>
val ps1 = dependentParams(tp.tp1, isUpper)
@@ -255,9 +255,9 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
*
* @param isUpper If true, `bound` is an upper bound, else a lower bound.
*/
- private def stripParams(tp: Type, paramBuf: mutable.ListBuffer[PolyParam],
+ private def stripParams(tp: Type, paramBuf: mutable.ListBuffer[TypeParamRef],
isUpper: Boolean)(implicit ctx: Context): Type = tp match {
- case param: PolyParam if contains(param) =>
+ case param: TypeParamRef if contains(param) =>
if (!paramBuf.contains(param)) paramBuf += param
NoType
case tp: AndOrType if isUpper == tp.isAnd =>
@@ -275,16 +275,16 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
* A top or bottom type if type consists only of dependent parameters.
* @param isUpper If true, `bound` is an upper bound, else a lower bound.
*/
- private def normalizedType(tp: Type, paramBuf: mutable.ListBuffer[PolyParam],
+ private def normalizedType(tp: Type, paramBuf: mutable.ListBuffer[TypeParamRef],
isUpper: Boolean)(implicit ctx: Context): Type =
stripParams(tp, paramBuf, isUpper)
.orElse(if (isUpper) defn.AnyType else defn.NothingType)
- def add(poly: PolyType, tvars: List[TypeVar])(implicit ctx: Context): This = {
+ def add(poly: TypeLambda, tvars: List[TypeVar])(implicit ctx: Context): This = {
assert(!contains(poly))
val nparams = poly.paramNames.length
val entries1 = new Array[Type](nparams * 2)
- poly.paramBounds.copyToArray(entries1, 0)
+ poly.paramInfos.copyToArray(entries1, 0)
tvars.copyToArray(entries1, nparams)
newConstraint(boundsMap.updated(poly, entries1), lowerMap, upperMap).init(poly)
}
@@ -293,12 +293,12 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
* Update all bounds to be normalized and update ordering to account for
* dependent parameters.
*/
- private def init(poly: PolyType)(implicit ctx: Context): This = {
+ private def init(poly: TypeLambda)(implicit ctx: Context): This = {
var current = this
- val loBuf, hiBuf = new mutable.ListBuffer[PolyParam]
+ val loBuf, hiBuf = new mutable.ListBuffer[TypeParamRef]
var i = 0
while (i < poly.paramNames.length) {
- val param = PolyParam(poly, i)
+ val param = TypeParamRef(poly, i)
val bounds = nonParamBounds(param)
val lo = normalizedType(bounds.lo, loBuf, isUpper = false)
val hi = normalizedType(bounds.hi, hiBuf, isUpper = true)
@@ -318,7 +318,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
/** Add the fact `param1 <: param2` to the constraint `current` and propagate
* `<:<` relationships between parameters ("edges") but not bounds.
*/
- private def order(current: This, param1: PolyParam, param2: PolyParam)(implicit ctx: Context): This =
+ private def order(current: This, param1: TypeParamRef, param2: TypeParamRef)(implicit ctx: Context): This =
if (param1 == param2 || current.isLess(param1, param2)) this
else {
assert(contains(param1))
@@ -330,10 +330,10 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
current2
}
- def addLess(param1: PolyParam, param2: PolyParam)(implicit ctx: Context): This =
+ def addLess(param1: TypeParamRef, param2: TypeParamRef)(implicit ctx: Context): This =
order(this, param1, param2)
- def updateEntry(current: This, param: PolyParam, tp: Type)(implicit ctx: Context): This = {
+ def updateEntry(current: This, param: TypeParamRef, tp: Type)(implicit ctx: Context): This = {
var current1 = boundsLens.update(this, current, param, tp)
tp match {
case TypeBounds(lo, hi) =>
@@ -346,10 +346,10 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
current1
}
- def updateEntry(param: PolyParam, tp: Type)(implicit ctx: Context): This =
+ def updateEntry(param: TypeParamRef, tp: Type)(implicit ctx: Context): This =
updateEntry(this, param, tp)
- def unify(p1: PolyParam, p2: PolyParam)(implicit ctx: Context): This = {
+ def unify(p1: TypeParamRef, p2: TypeParamRef)(implicit ctx: Context): This = {
val p1Bounds = (nonParamBounds(p1) & nonParamBounds(p2)).substParam(p2, p1)
updateEntry(p1, p1Bounds).replace(p2, p1)
}
@@ -381,7 +381,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
* would not find out where we need to approximate. Occurrences of parameters
* that are not top-level are not affected.
*/
- def replace(param: PolyParam, tp: Type)(implicit ctx: Context): OrderingConstraint = {
+ def replace(param: TypeParamRef, tp: Type)(implicit ctx: Context): OrderingConstraint = {
val replacement = tp.dealias.stripTypeVar
if (param == replacement) this
else {
@@ -389,10 +389,10 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
val poly = param.binder
val idx = param.paramNum
- def removeParam(ps: List[PolyParam]) =
+ def removeParam(ps: List[TypeParamRef]) =
ps.filterNot(p => p.binder.eq(poly) && p.paramNum == idx)
- def replaceParam(tp: Type, atPoly: PolyType, atIdx: Int): Type = tp match {
+ def replaceParam(tp: Type, atPoly: TypeLambda, atIdx: Int): Type = tp match {
case bounds @ TypeBounds(lo, hi) =>
def recombine(andor: AndOrType, op: (Type, Boolean) => Type, isUpper: Boolean): Type = {
@@ -404,7 +404,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
}
def normalize(tp: Type, isUpper: Boolean): Type = tp match {
- case p: PolyParam if p.binder == atPoly && p.paramNum == atIdx =>
+ case p: TypeParamRef if p.binder == atPoly && p.paramNum == atIdx =>
if (isUpper) defn.AnyType else defn.NothingType
case tp: AndOrType if isUpper == tp.isAnd => recombine(tp, normalize, isUpper)
case _ => tp
@@ -432,9 +432,9 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
}
}
- def remove(pt: PolyType)(implicit ctx: Context): This = {
+ def remove(pt: TypeLambda)(implicit ctx: Context): This = {
def removeFromOrdering(po: ParamOrdering) = {
- def removeFromBoundss(key: PolyType, bndss: Array[List[PolyParam]]): Array[List[PolyParam]] = {
+ def removeFromBoundss(key: TypeLambda, bndss: Array[List[TypeParamRef]]): Array[List[TypeParamRef]] = {
val bndss1 = bndss.map(_.filterConserve(_.binder ne pt))
if (bndss.corresponds(bndss1)(_ eq _)) bndss else bndss1
}
@@ -443,7 +443,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
newConstraint(boundsMap.remove(pt), removeFromOrdering(lowerMap), removeFromOrdering(upperMap))
}
- def isRemovable(pt: PolyType): Boolean = {
+ def isRemovable(pt: TypeLambda): Boolean = {
val entries = boundsMap(pt)
@tailrec def allRemovable(last: Int): Boolean =
if (last < 0) true
@@ -456,24 +456,24 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
// ---------- Exploration --------------------------------------------------------
- def domainPolys: List[PolyType] = boundsMap.keys
+ def domainLambdas: List[TypeLambda] = boundsMap.keys
- def domainParams: List[PolyParam] =
+ def domainParams: List[TypeParamRef] =
for {
(poly, entries) <- boundsMap.toList
n <- 0 until paramCount(entries)
if entries(n).exists
- } yield PolyParam(poly, n)
+ } yield TypeParamRef(poly, n)
- def forallParams(p: PolyParam => Boolean): Boolean = {
+ def forallParams(p: TypeParamRef => Boolean): Boolean = {
boundsMap.foreachBinding { (poly, entries) =>
for (i <- 0 until paramCount(entries))
- if (isBounds(entries(i)) && !p(PolyParam(poly, i))) return false
+ if (isBounds(entries(i)) && !p(TypeParamRef(poly, i))) return false
}
true
}
- def foreachParam(p: (PolyType, Int) => Unit): Unit =
+ def foreachParam(p: (TypeLambda, Int) => Unit): Unit =
boundsMap.foreachBinding { (poly, entries) =>
0.until(poly.paramNames.length).foreach(p(poly, _))
}
@@ -503,7 +503,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
merged
}
- def mergeParams(ps1: List[PolyParam], ps2: List[PolyParam]) =
+ def mergeParams(ps1: List[TypeParamRef], ps2: List[TypeParamRef]) =
(ps1 /: ps2)((ps1, p2) => if (ps1.contains(p2)) ps1 else p2 :: ps1)
def mergeEntries(e1: Type, e2: Type): Type = e1 match {
@@ -532,13 +532,13 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
}
override def checkClosed()(implicit ctx: Context): Unit = {
- def isFreePolyParam(tp: Type) = tp match {
- case PolyParam(binder: PolyType, _) => !contains(binder)
+ def isFreeTypeParamRef(tp: Type) = tp match {
+ case TypeParamRef(binder: TypeLambda, _) => !contains(binder)
case _ => false
}
def checkClosedType(tp: Type, where: String) =
if (tp != null)
- assert(!tp.existsPart(isFreePolyParam), i"unclosed constraint: $this refers to $tp in $where")
+ assert(!tp.existsPart(isFreeTypeParamRef), i"unclosed constraint: $this refers to $tp in $where")
boundsMap.foreachBinding((_, tps) => tps.foreach(checkClosedType(_, "bounds")))
lowerMap.foreachBinding((_, paramss) => paramss.foreach(_.foreach(checkClosedType(_, "lower"))))
upperMap.foreachBinding((_, paramss) => paramss.foreach(_.foreach(checkClosedType(_, "upper"))))
@@ -567,7 +567,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
def checkNonCyclic()(implicit ctx: Context): Unit =
domainParams.foreach(checkNonCyclic)
- private def checkNonCyclic(param: PolyParam)(implicit ctx: Context): Unit =
+ private def checkNonCyclic(param: TypeParamRef)(implicit ctx: Context): Unit =
assert(!isLess(param, param), i"cyclic constraint involving $param in $this")
// ---------- toText -----------------------------------------------------
@@ -584,7 +584,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
val uninstVarsText = " uninstVars = " ~
Text(uninstVars map (_.toText(printer)), ", ") ~ ";"
val constrainedText =
- " constrained types = " ~ Text(domainPolys map (_.toText(printer)), ", ")
+ " constrained types = " ~ Text(domainLambdas map (_.toText(printer)), ", ")
val boundsText =
" bounds = " ~ {
val assocs =
@@ -614,8 +614,8 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
case _ =>" := " + tp
}
val constrainedText =
- " constrained types = " + domainPolys.mkString("\n")
- val boundsText =
+ " constrained types = " + domainLambdas.mkString("\n")
+ val boundsText = domainLambdas
" bounds = " + {
val assocs =
for (param <- domainParams)
diff --git a/compiler/src/dotty/tools/dotc/core/TypeParamInfo.scala b/compiler/src/dotty/tools/dotc/core/ParamInfo.scala
index 647c895db..46e378fc2 100644
--- a/compiler/src/dotty/tools/dotc/core/TypeParamInfo.scala
+++ b/compiler/src/dotty/tools/dotc/core/ParamInfo.scala
@@ -1,13 +1,15 @@
package dotty.tools.dotc.core
-import Names.TypeName
+import Names.Name
import Contexts.Context
-import Types.{Type, TypeBounds}
+import Types.Type
/** A common super trait of Symbol and LambdaParam.
* Used to capture the attributes of type parameters which can be implemented as either.
*/
-trait TypeParamInfo {
+trait ParamInfo {
+
+ type ThisName <: Name
/** Is this the info of a type parameter? Will return `false` for symbols
* that are not type parameters.
@@ -15,26 +17,30 @@ trait TypeParamInfo {
def isTypeParam(implicit ctx: Context): Boolean
/** The name of the type parameter */
- def paramName(implicit ctx: Context): TypeName
+ def paramName(implicit ctx: Context): ThisName
/** The info of the type parameter */
- def paramBounds(implicit ctx: Context): TypeBounds
+ def paramInfo(implicit ctx: Context): Type
/** The info of the type parameter as seen from a prefix type.
* For type parameter symbols, this is the `memberInfo` as seen from `prefix`.
- * For type lambda parameters, it's the same as `paramBounds` as
+ * For type lambda parameters, it's the same as `paramInfos` as
* `asSeenFrom` has already been applied to the whole type lambda.
*/
- def paramBoundsAsSeenFrom(pre: Type)(implicit ctx: Context): TypeBounds
+ def paramInfoAsSeenFrom(pre: Type)(implicit ctx: Context): Type
/** The parameter bounds, or the completer if the type parameter
* is an as-yet uncompleted symbol.
*/
- def paramBoundsOrCompleter(implicit ctx: Context): Type
+ def paramInfoOrCompleter(implicit ctx: Context): Type
/** The variance of the type parameter */
def paramVariance(implicit ctx: Context): Int
/** A type that refers to the parameter */
def paramRef(implicit ctx: Context): Type
+}
+
+object ParamInfo {
+ type Of[N] = ParamInfo { type ThisName = N }
} \ No newline at end of file
diff --git a/compiler/src/dotty/tools/dotc/core/StdNames.scala b/compiler/src/dotty/tools/dotc/core/StdNames.scala
index 5b7dc3d1d..e7928fd09 100644
--- a/compiler/src/dotty/tools/dotc/core/StdNames.scala
+++ b/compiler/src/dotty/tools/dotc/core/StdNames.scala
@@ -132,6 +132,8 @@ object StdNames {
val TRAIT_SETTER_SEPARATOR: N = "$_setter_$"
val DIRECT_SUFFIX: N = "$direct"
val LAZY_IMPLICIT_PREFIX: N = "$lazy_implicit$"
+ val DOLLAR_VALUES: N = "$values"
+ val DOLLAR_NEW: N = "$new"
// value types (and AnyRef) are all used as terms as well
// as (at least) arguments to the @specialize annotation.
@@ -395,6 +397,7 @@ object StdNames {
val elem: N = "elem"
val emptyValDef: N = "emptyValDef"
val ensureAccessible : N = "ensureAccessible"
+ val enumTag: N = "enumTag"
val eq: N = "eq"
val equalsNumChar : N = "equalsNumChar"
val equalsNumNum : N = "equalsNumNum"
@@ -499,6 +502,7 @@ object StdNames {
val staticModule : N = "staticModule"
val staticPackage : N = "staticPackage"
val synchronized_ : N = "synchronized"
+ val tag: N = "tag"
val tail: N = "tail"
val `then` : N = "then"
val this_ : N = "this"
@@ -523,7 +527,7 @@ object StdNames {
val updateDynamic: N = "updateDynamic"
val value: N = "value"
val valueOf : N = "valueOf"
- val values : N = "values"
+ val values: N = "values"
val view_ : N = "view"
val wait_ : N = "wait"
val withFilter: N = "withFilter"
@@ -718,9 +722,6 @@ object StdNames {
case _ => termName("_" + j)
}
- def syntheticParamNames(num: Int): List[TermName] =
- (0 until num).map(syntheticParamName)(breakOut)
-
def localDummyName(clazz: Symbol)(implicit ctx: Context): TermName =
LOCALDUMMY_PREFIX ++ clazz.name ++ ">"
@@ -743,9 +744,6 @@ object StdNames {
def syntheticTypeParamName(i: Int): TypeName = "X" + i
- def syntheticTypeParamNames(num: Int): List[TypeName] =
- (0 until num).map(syntheticTypeParamName)(breakOut)
-
final val Conforms = encode("<:<")
final val Uninstantiated: TypeName = "?$"
@@ -846,5 +844,4 @@ object StdNames {
val tpnme = new ScalaTypeNames
val jnme = new JavaTermNames
val jtpnme = new JavaTypeNames
-
}
diff --git a/compiler/src/dotty/tools/dotc/core/Substituters.scala b/compiler/src/dotty/tools/dotc/core/Substituters.scala
index 23683608a..d565ec229 100644
--- a/compiler/src/dotty/tools/dotc/core/Substituters.scala
+++ b/compiler/src/dotty/tools/dotc/core/Substituters.scala
@@ -196,7 +196,7 @@ trait Substituters { this: Context =>
.mapOver(tp)
}
- final def substParam(tp: Type, from: ParamType, to: Type, theMap: SubstParamMap): Type =
+ final def substParam(tp: Type, from: ParamRef, to: Type, theMap: SubstParamMap): Type =
tp match {
case tp: BoundType =>
if (tp == from) to else tp
@@ -216,7 +216,7 @@ trait Substituters { this: Context =>
final def substParams(tp: Type, from: BindingType, to: List[Type], theMap: SubstParamsMap): Type =
tp match {
- case tp: ParamType =>
+ case tp: ParamRef =>
if (tp.binder == from) to(tp.paramNum) else tp
case tp: NamedType =>
if (tp.currentSymbol.isStatic) tp
@@ -269,7 +269,7 @@ trait Substituters { this: Context =>
def apply(tp: Type): Type = substRecThis(tp, from, to, this)
}
- final class SubstParamMap(from: ParamType, to: Type) extends DeepTypeMap {
+ final class SubstParamMap(from: ParamRef, to: Type) extends DeepTypeMap {
def apply(tp: Type) = substParam(tp, from, to, this)
}
diff --git a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala
index db96463e0..602848a50 100644
--- a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala
+++ b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala
@@ -163,26 +163,31 @@ object SymDenotations {
setFlag(flags & mask)
}
+ private def isCurrent(fs: FlagSet) =
+ fs <= (
+ if (myInfo.isInstanceOf[SymbolLoader]) FromStartFlags
+ else AfterLoadFlags)
+
/** Has this denotation one of the flags in `fs` set? */
final def is(fs: FlagSet)(implicit ctx: Context) = {
- (if (fs <= FromStartFlags) myFlags else flags) is fs
+ (if (isCurrent(fs)) myFlags else flags) is fs
}
/** Has this denotation one of the flags in `fs` set, whereas none of the flags
* in `butNot` are set?
*/
final def is(fs: FlagSet, butNot: FlagSet)(implicit ctx: Context) =
- (if (fs <= FromStartFlags && butNot <= FromStartFlags) myFlags else flags) is (fs, butNot)
+ (if (isCurrent(fs) && isCurrent(butNot)) myFlags else flags) is (fs, butNot)
/** Has this denotation all of the flags in `fs` set? */
final def is(fs: FlagConjunction)(implicit ctx: Context) =
- (if (fs <= FromStartFlags) myFlags else flags) is fs
+ (if (isCurrent(fs)) myFlags else flags) is fs
/** Has this denotation all of the flags in `fs` set, whereas none of the flags
* in `butNot` are set?
*/
final def is(fs: FlagConjunction, butNot: FlagSet)(implicit ctx: Context) =
- (if (fs <= FromStartFlags && butNot <= FromStartFlags) myFlags else flags) is (fs, butNot)
+ (if (isCurrent(fs) && isCurrent(butNot)) myFlags else flags) is (fs, butNot)
/** The type info.
* The info is an instance of TypeType iff this is a type denotation
@@ -1141,14 +1146,13 @@ object SymDenotations {
case tp: NamedType => hasSkolems(tp.prefix)
case tp: RefinedType => hasSkolems(tp.parent) || hasSkolems(tp.refinedInfo)
case tp: RecType => hasSkolems(tp.parent)
- case tp: PolyType => tp.paramBounds.exists(hasSkolems) || hasSkolems(tp.resType)
- case tp: MethodType => tp.paramTypes.exists(hasSkolems) || hasSkolems(tp.resType)
+ case tp: TypeBounds => hasSkolems(tp.lo) || hasSkolems(tp.hi)
+ case tp: TypeVar => hasSkolems(tp.inst)
case tp: ExprType => hasSkolems(tp.resType)
case tp: HKApply => hasSkolems(tp.tycon) || tp.args.exists(hasSkolems)
+ case tp: LambdaType => tp.paramInfos.exists(hasSkolems) || hasSkolems(tp.resType)
case tp: AndOrType => hasSkolems(tp.tp1) || hasSkolems(tp.tp2)
- case tp: TypeBounds => hasSkolems(tp.lo) || hasSkolems(tp.hi)
case tp: AnnotatedType => hasSkolems(tp.tpe)
- case tp: TypeVar => hasSkolems(tp.inst)
case _ => false
}
diff --git a/compiler/src/dotty/tools/dotc/core/Symbols.scala b/compiler/src/dotty/tools/dotc/core/Symbols.scala
index 33aba4d13..95ff1cb75 100644
--- a/compiler/src/dotty/tools/dotc/core/Symbols.scala
+++ b/compiler/src/dotty/tools/dotc/core/Symbols.scala
@@ -384,7 +384,7 @@ object Symbols {
* @param coord The coordinates of the symbol (a position or an index)
* @param id A unique identifier of the symbol (unique per ContextBase)
*/
- class Symbol private[Symbols] (val coord: Coord, val id: Int) extends DotClass with TypeParamInfo with printing.Showable {
+ class Symbol private[Symbols] (val coord: Coord, val id: Int) extends DotClass with ParamInfo with printing.Showable {
type ThisName <: Name
@@ -513,12 +513,12 @@ object Symbols {
*/
def pos: Position = if (coord.isPosition) coord.toPosition else NoPosition
- // TypeParamInfo methods
+ // ParamInfo types and methods
def isTypeParam(implicit ctx: Context) = denot.is(TypeParam)
- def paramName(implicit ctx: Context) = name.asTypeName
- def paramBounds(implicit ctx: Context) = denot.info.bounds
- def paramBoundsAsSeenFrom(pre: Type)(implicit ctx: Context) = pre.memberInfo(this).bounds
- def paramBoundsOrCompleter(implicit ctx: Context): Type = denot.infoOrCompleter
+ def paramName(implicit ctx: Context) = name.asInstanceOf[ThisName]
+ def paramInfo(implicit ctx: Context) = denot.info
+ def paramInfoAsSeenFrom(pre: Type)(implicit ctx: Context) = pre.memberInfo(this)
+ def paramInfoOrCompleter(implicit ctx: Context): Type = denot.infoOrCompleter
def paramVariance(implicit ctx: Context) = denot.variance
def paramRef(implicit ctx: Context) = denot.typeRef
diff --git a/compiler/src/dotty/tools/dotc/core/TypeApplications.scala b/compiler/src/dotty/tools/dotc/core/TypeApplications.scala
index ba3e6a461..23c3f96cc 100644
--- a/compiler/src/dotty/tools/dotc/core/TypeApplications.scala
+++ b/compiler/src/dotty/tools/dotc/core/TypeApplications.scala
@@ -21,6 +21,8 @@ import java.util.NoSuchElementException
object TypeApplications {
+ type TypeParamInfo = ParamInfo.Of[TypeName]
+
/** Assert type is not a TypeBounds instance and return it unchanged */
val noBounds = (tp: Type) => tp match {
case tp: TypeBounds => throw new AssertionError("no TypeBounds allowed")
@@ -73,7 +75,7 @@ object TypeApplications {
}
def unapply(tp: Type)(implicit ctx: Context): Option[TypeRef] = tp match {
- case tp @ PolyType(tparams, AppliedType(fn: TypeRef, args)) if (args == tparams.map(_.toArg)) => Some(fn)
+ case tp @ HKTypeLambda(tparams, AppliedType(fn: TypeRef, args)) if (args == tparams.map(_.toArg)) => Some(fn)
case _ => None
}
}
@@ -119,7 +121,7 @@ object TypeApplications {
*/
def EtaExpandIfHK(tparams: List[TypeParamInfo], args: List[Type])(implicit ctx: Context): List[Type] =
if (tparams.isEmpty) args
- else args.zipWithConserve(tparams)((arg, tparam) => arg.EtaExpandIfHK(tparam.paramBoundsOrCompleter))
+ else args.zipWithConserve(tparams)((arg, tparam) => arg.EtaExpandIfHK(tparam.paramInfoOrCompleter))
/** A type map that tries to reduce (part of) the result type of the type lambda `tycon`
* with the given `args`(some of which are wildcard arguments represented by type bounds).
@@ -160,18 +162,18 @@ object TypeApplications {
* result type. Using this mode, we can guarantee that `appliedTo` will never
* produce a higher-kinded application with a type lambda as type constructor.
*/
- class Reducer(tycon: PolyType, args: List[Type])(implicit ctx: Context) extends TypeMap {
+ class Reducer(tycon: TypeLambda, args: List[Type])(implicit ctx: Context) extends TypeMap {
private var available = (0 until args.length).toSet
var allReplaced = true
- def hasWildcardArg(p: PolyParam) =
+ def hasWildcardArg(p: TypeParamRef) =
p.binder == tycon && args(p.paramNum).isInstanceOf[TypeBounds]
- def canReduceWildcard(p: PolyParam) =
+ def canReduceWildcard(p: TypeParamRef) =
!ctx.mode.is(Mode.AllowLambdaWildcardApply) || available.contains(p.paramNum)
def apply(t: Type) = t match {
- case t @ TypeAlias(p: PolyParam) if hasWildcardArg(p) && canReduceWildcard(p) =>
+ case t @ TypeAlias(p: TypeParamRef) if hasWildcardArg(p) && canReduceWildcard(p) =>
available -= p.paramNum
args(p.paramNum)
- case p: PolyParam if p.binder == tycon =>
+ case p: TypeParamRef if p.binder == tycon =>
args(p.paramNum) match {
case TypeBounds(lo, hi) =>
if (ctx.mode.is(Mode.AllowLambdaWildcardApply)) { allReplaced = false; p }
@@ -213,7 +215,7 @@ class TypeApplications(val self: Type) extends AnyVal {
self match {
case self: ClassInfo =>
self.cls.typeParams
- case self: PolyType =>
+ case self: HKTypeLambda =>
self.typeParams
case self: TypeRef =>
val tsym = self.symbol
@@ -251,7 +253,7 @@ class TypeApplications(val self: Type) extends AnyVal {
def isHK(implicit ctx: Context): Boolean = self.dealias match {
case self: TypeRef => self.info.isHK
case self: RefinedType => false
- case self: PolyType => true
+ case self: HKTypeLambda => true
case self: SingletonType => false
case self: TypeVar =>
// Using `origin` instead of `underlying`, as is done for typeParams,
@@ -270,31 +272,6 @@ class TypeApplications(val self: Type) extends AnyVal {
self
}
- /** Lambda abstract `self` with given type parameters. Examples:
- *
- * type T[X] = U becomes type T = [X] -> U
- * type T[X] >: L <: U becomes type T >: L <: ([X] -> U)
- *
- * TODO: Handle parameterized lower bounds
- */
- def LambdaAbstract(tparams: List[TypeParamInfo])(implicit ctx: Context): Type = {
- def expand(tp: Type) =
- PolyType(
- tparams.map(_.paramName), tparams.map(_.paramVariance))(
- tl => tparams.map(tparam => tl.lifted(tparams, tparam.paramBounds).bounds),
- tl => tl.lifted(tparams, tp))
- if (tparams.isEmpty) self
- else self match {
- case self: TypeAlias =>
- self.derivedTypeAlias(expand(self.alias))
- case self @ TypeBounds(lo, hi) =>
- self.derivedTypeBounds(
- if (lo.isRef(defn.NothingClass)) lo else expand(lo),
- expand(hi))
- case _ => expand(self)
- }
- }
-
/** Convert a type constructor `TC` which has type parameters `T1, ..., Tn`
* in a context where type parameters `U1,...,Un` are expected to
*
@@ -307,7 +284,7 @@ class TypeApplications(val self: Type) extends AnyVal {
*/
def EtaExpand(tparams: List[TypeSymbol])(implicit ctx: Context): Type = {
val tparamsToUse = if (variancesConform(typeParams, tparams)) tparams else typeParamSymbols
- self.appliedTo(tparams map (_.typeRef)).LambdaAbstract(tparamsToUse)
+ HKTypeLambda.fromParams(tparamsToUse, self.appliedTo(tparams map (_.typeRef)))
//.ensuring(res => res.EtaReduce =:= self, s"res = $res, core = ${res.EtaReduce}, self = $self, hc = ${res.hashCode}")
}
@@ -362,11 +339,13 @@ class TypeApplications(val self: Type) extends AnyVal {
if (hkParams.isEmpty) self
else {
def adaptArg(arg: Type): Type = arg match {
- case arg @ PolyType(tparams, body) if
+ case arg @ HKTypeLambda(tparams, body) if
!tparams.corresponds(hkParams)(_.paramVariance == _.paramVariance) &&
tparams.corresponds(hkParams)(varianceConforms) =>
- PolyType(tparams.map(_.paramName), hkParams.map(_.paramVariance))(
- tl => arg.paramBounds.map(_.subst(arg, tl).bounds),
+ HKTypeLambda(
+ (tparams, hkParams).zipped.map((tparam, hkparam) =>
+ tparam.paramName.withVariance(hkparam.paramVariance)))(
+ tl => arg.paramInfos.map(_.subst(arg, tl).bounds),
tl => arg.resultType.subst(arg, tl)
)
case arg @ TypeAlias(alias) =>
@@ -390,7 +369,7 @@ class TypeApplications(val self: Type) extends AnyVal {
*/
final def appliedTo(args: List[Type])(implicit ctx: Context): Type = /*>|>*/ track("appliedTo") /*<|<*/ {
val typParams = self.typeParams
- def matchParams(t: Type, tparams: List[TypeParamInfo], args: List[Type])(implicit ctx: Context): Type = args match {
+ def matchParams(t: Type, tparams: List[ParamInfo], args: List[Type])(implicit ctx: Context): Type = args match {
case arg :: args1 =>
try {
val tparam :: tparams1 = tparams
@@ -407,7 +386,7 @@ class TypeApplications(val self: Type) extends AnyVal {
val dealiased = stripped.safeDealias
if (args.isEmpty || ctx.erasedTypes) self
else dealiased match {
- case dealiased: PolyType =>
+ case dealiased: HKTypeLambda =>
def tryReduce =
if (!args.exists(_.isInstanceOf[TypeBounds])) {
val followAlias = Config.simplifyApplications && {
@@ -426,7 +405,7 @@ class TypeApplications(val self: Type) extends AnyVal {
// In this case we should always dealias since we cannot handle
// higher-kinded applications to wildcard arguments.
dealiased
- .derivedPolyType(resType = tycon.safeDealias.appliedTo(args1))
+ .derivedLambdaType(resType = tycon.safeDealias.appliedTo(args1))
.appliedTo(args)
case _ =>
val reducer = new Reducer(dealiased, args)
@@ -435,6 +414,8 @@ class TypeApplications(val self: Type) extends AnyVal {
else HKApply(dealiased, args)
}
tryReduce
+ case dealiased: PolyType =>
+ dealiased.instantiate(args)
case dealiased: AndOrType =>
dealiased.derivedAndOrType(dealiased.tp1.appliedTo(args), dealiased.tp2.appliedTo(args))
case dealiased: TypeAlias =>
@@ -475,7 +456,7 @@ class TypeApplications(val self: Type) extends AnyVal {
/** Turn this type, which is used as an argument for
* type parameter `tparam`, into a TypeBounds RHS
*/
- final def toBounds(tparam: TypeParamInfo)(implicit ctx: Context): TypeBounds = self match {
+ final def toBounds(tparam: ParamInfo)(implicit ctx: Context): TypeBounds = self match {
case self: TypeBounds => // this can happen for wildcard args
self
case _ =>
diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala
index 57dde3288..da6d63387 100644
--- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala
+++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala
@@ -280,7 +280,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
case _ =>
}
thirdTry(tp1, tp2)
- case tp1: PolyParam =>
+ case tp1: TypeParamRef =>
def flagNothingBound = {
if (!frozenConstraint && tp2.isRef(defn.NothingClass) && state.isGlobalCommittable) {
def msg = s"!!! instantiated to Nothing: $tp1, constraint = ${constraint.show}"
@@ -289,13 +289,13 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
}
true
}
- def comparePolyParam =
+ def compareTypeParamRef =
ctx.mode.is(Mode.TypevarsMissContext) ||
isSubTypeWhenFrozen(bounds(tp1).hi, tp2) || {
if (canConstrain(tp1)) addConstraint(tp1, tp2, fromBelow = false) && flagNothingBound
else thirdTry(tp1, tp2)
}
- comparePolyParam
+ compareTypeParamRef
case tp1: ThisType =>
val cls1 = tp1.cls
tp2 match {
@@ -373,8 +373,8 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
private def thirdTry(tp1: Type, tp2: Type): Boolean = tp2 match {
case tp2: NamedType =>
thirdTryNamed(tp1, tp2)
- case tp2: PolyParam =>
- def comparePolyParam =
+ case tp2: TypeParamRef =>
+ def compareTypeParamRef =
(ctx.mode is Mode.TypevarsMissContext) || {
val alwaysTrue =
// The following condition is carefully formulated to catch all cases
@@ -391,7 +391,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
else fourthTry(tp1, tp2)
}
}
- comparePolyParam
+ compareTypeParamRef
case tp2: RefinedType =>
def compareRefinedSlow: Boolean = {
val name2 = tp2.refinedName
@@ -428,9 +428,9 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
compareRec
case tp2 @ HKApply(tycon2, args2) =>
compareHkApply2(tp1, tp2, tycon2, args2)
- case tp2 @ PolyType(tparams2, body2) =>
- def compareHkLambda: Boolean = tp1.stripTypeVar match {
- case tp1 @ PolyType(tparams1, body1) =>
+ case tp2: HKTypeLambda =>
+ def compareTypeLambda: Boolean = tp1.stripTypeVar match {
+ case tp1: HKTypeLambda =>
/* Don't compare bounds of lambdas under language:Scala2, or t2994 will fail
* The issue is that, logically, bounds should compare contravariantly,
* but that would invalidate a pattern exploited in t2994:
@@ -446,16 +446,16 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
*/
def boundsOK =
ctx.scala2Mode ||
- tparams1.corresponds(tparams2)((tparam1, tparam2) =>
- isSubType(tparam2.paramBounds.subst(tp2, tp1), tparam1.paramBounds))
- val saved = comparedPolyTypes
- comparedPolyTypes += tp1
- comparedPolyTypes += tp2
+ tp1.typeParams.corresponds(tp2.typeParams)((tparam1, tparam2) =>
+ isSubType(tparam2.paramInfo.subst(tp2, tp1), tparam1.paramInfo))
+ val saved = comparedTypeLambdas
+ comparedTypeLambdas += tp1
+ comparedTypeLambdas += tp2
try
- variancesConform(tparams1, tparams2) &&
+ variancesConform(tp1.typeParams, tp2.typeParams) &&
boundsOK &&
- isSubType(body1, body2.subst(tp2, tp1))
- finally comparedPolyTypes = saved
+ isSubType(tp1.resType, tp2.resType.subst(tp2, tp1))
+ finally comparedTypeLambdas = saved
case _ =>
if (!tp1.isHK) {
tp2 match {
@@ -466,7 +466,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
}
fourthTry(tp1, tp2)
}
- compareHkLambda
+ compareTypeLambda
case OrType(tp21, tp22) =>
// Rewrite T1 <: (T211 & T212) | T22 to T1 <: (T211 | T22) and T1 <: (T212 | T22)
// and analogously for T1 <: T21 | (T221 & T222)
@@ -484,12 +484,12 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
case _ =>
}
either(isSubType(tp1, tp21), isSubType(tp1, tp22)) || fourthTry(tp1, tp2)
- case tp2: MethodType =>
+ case tp2: MethodOrPoly =>
def compareMethod = tp1 match {
- case tp1: MethodType =>
+ case tp1: MethodOrPoly =>
(tp1.signature consistentParams tp2.signature) &&
- matchingParams(tp1.paramTypes, tp2.paramTypes, tp1.isJava, tp2.isJava) &&
- (tp1.isImplicit == tp2.isImplicit) &&
+ matchingParams(tp1, tp2) &&
+ tp1.isImplicit == tp2.isImplicit &&
isSubType(tp1.resultType, tp2.resultType.subst(tp2, tp1))
case _ =>
false
@@ -618,7 +618,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
def isMatchingApply(tp1: Type): Boolean = tp1 match {
case HKApply(tycon1, args1) =>
tycon1.dealias match {
- case tycon1: PolyParam =>
+ case tycon1: TypeParamRef =>
(tycon1 == tycon2 ||
canConstrain(tycon1) && tryInstantiate(tycon1, tycon2)) &&
isSubArgs(args1, args2, tparams)
@@ -646,7 +646,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
* and the resulting type application is a supertype of `tp1`,
* or fallback to fourthTry.
*/
- def canInstantiate(tycon2: PolyParam): Boolean = {
+ def canInstantiate(tycon2: TypeParamRef): Boolean = {
/** Let
*
@@ -669,10 +669,10 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
val tparams1 = tparams1a.drop(lengthDiff)
variancesConform(tparams1, tparams) && {
if (lengthDiff > 0)
- tycon1b = PolyType(tparams1.map(_.paramName), tparams1.map(_.paramVariance))(
- tl => tparams1.map(tparam => tl.lifted(tparams, tparam.paramBounds).bounds),
+ tycon1b = HKTypeLambda(tparams1.map(_.paramName))(
+ tl => tparams1.map(tparam => tl.integrate(tparams, tparam.paramInfo).bounds),
tl => tycon1a.appliedTo(args1.take(lengthDiff) ++
- tparams1.indices.toList.map(PolyParam(tl, _))))
+ tparams1.indices.toList.map(TypeParamRef(tl, _))))
(ctx.mode.is(Mode.TypevarsMissContext) ||
tryInstantiate(tycon2, tycon1b.ensureHK)) &&
isSubType(tp1, tycon1b.appliedTo(args2))
@@ -725,7 +725,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
fallback(tycon2bounds.lo)
tycon2 match {
- case param2: PolyParam =>
+ case param2: TypeParamRef =>
isMatchingApply(tp1) || {
if (canConstrain(param2)) canInstantiate(param2)
else compareLower(bounds(param2), tyconIsTypeRef = false)
@@ -746,7 +746,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
*/
def compareHkApply1(tp1: HKApply, tycon1: Type, args1: List[Type], tp2: Type): Boolean =
tycon1 match {
- case param1: PolyParam =>
+ case param1: TypeParamRef =>
def canInstantiate = tp2 match {
case AppliedType(tycon2, args2) =>
tryInstantiate(param1, tycon2.ensureHK) && isSubArgs(args1, args2, tycon2.typeParams)
@@ -764,7 +764,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
/** Subtype test for corresponding arguments in `args1`, `args2` according to
* variances in type parameters `tparams`.
*/
- def isSubArgs(args1: List[Type], args2: List[Type], tparams: List[TypeParamInfo]): Boolean =
+ def isSubArgs(args1: List[Type], args2: List[Type], tparams: List[ParamInfo]): Boolean =
if (args1.isEmpty) args2.isEmpty
else args2.nonEmpty && {
val v = tparams.head.paramVariance
@@ -806,7 +806,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
def fix(tp: Type): Type = tp.stripTypeVar match {
case tp: RecType => fix(tp.parent).substRecThis(tp, anchor)
case tp @ RefinedType(parent, rname, rinfo) => tp.derivedRefinedType(fix(parent), rname, rinfo)
- case tp: PolyParam => fixOrElse(bounds(tp).hi, tp)
+ case tp: TypeParamRef => fixOrElse(bounds(tp).hi, tp)
case tp: TypeProxy => fixOrElse(tp.underlying, tp)
case tp: AndOrType => tp.derivedAndOrType(fix(tp.tp1), fix(tp.tp2))
case tp => tp
@@ -967,7 +967,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
/** Defer constraining type variables when compared against prototypes */
def isMatchedByProto(proto: ProtoType, tp: Type) = tp.stripTypeVar match {
- case tp: PolyParam if constraint contains tp => true
+ case tp: TypeParamRef if constraint contains tp => true
case _ => proto.isMatchedBy(tp)
}
@@ -978,7 +978,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
* type variable with (the corresponding type in) `tp2` instead.
*/
private def isCappable(tp: Type): Boolean = tp match {
- case tp: PolyParam => constraint contains tp
+ case tp: TypeParamRef => constraint contains tp
case tp: TypeProxy => isCappable(tp.underlying)
case tp: AndOrType => isCappable(tp.tp1) || isCappable(tp.tp2)
case _ => false
@@ -1021,7 +1021,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
tp2.widen match {
case tp2: MethodType =>
// implicitness is ignored when matching
- matchingParams(tp1.paramTypes, tp2.paramTypes, tp1.isJava, tp2.isJava) &&
+ matchingParams(tp1, tp2) &&
matchesType(tp1.resultType, tp2.resultType.subst(tp2, tp1), relaxed)
case tp2 =>
relaxed && tp1.paramNames.isEmpty &&
@@ -1031,7 +1031,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
tp2.widen match {
case tp2: PolyType =>
sameLength(tp1.paramNames, tp2.paramNames) &&
- matchesType(tp1.resultType, tp2.resultType.subst(tp2, tp1), relaxed)
+ matchesType(tp1.resultType, tp2.resultType.subst(tp2, tp1), relaxed)
case _ =>
false
}
@@ -1047,28 +1047,28 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
}
}
- /** Are `syms1` and `syms2` parameter lists with pairwise equivalent types? */
- def matchingParams(formals1: List[Type], formals2: List[Type], isJava1: Boolean, isJava2: Boolean): Boolean = formals1 match {
- case formal1 :: rest1 =>
- formals2 match {
- case formal2 :: rest2 =>
- (isSameTypeWhenFrozen(formal1, formal2)
- || isJava1 && (formal2 isRef ObjectClass) && (formal1 isRef AnyClass)
- || isJava2 && (formal1 isRef ObjectClass) && (formal2 isRef AnyClass)) &&
- matchingParams(rest1, rest2, isJava1, isJava2)
- case nil =>
- false
- }
- case nil =>
- formals2.isEmpty
- }
-
- /** Do generic types `poly1` and `poly2` have type parameters that
- * have the same bounds (after renaming one set to the other)?
+ /** Do lambda types `lam1` and `lam2` have parameters that have the same types
+ * and the same implicit status? (after renaming one set to the other)
*/
- def matchingTypeParams(poly1: PolyType, poly2: PolyType): Boolean =
- (poly1.paramBounds corresponds poly2.paramBounds)((b1, b2) =>
- isSameType(b1, b2.subst(poly2, poly1)))
+ def matchingParams(lam1: MethodOrPoly, lam2: MethodOrPoly): Boolean = {
+ /** Are `syms1` and `syms2` parameter lists with pairwise equivalent types? */
+ def loop(formals1: List[Type], formals2: List[Type]): Boolean = formals1 match {
+ case formal1 :: rest1 =>
+ formals2 match {
+ case formal2 :: rest2 =>
+ val formal2a = if (lam2.isParamDependent) formal2.subst(lam2, lam1) else formal2
+ (isSameTypeWhenFrozen(formal1, formal2a)
+ || lam1.isJava && (formal2 isRef ObjectClass) && (formal1 isRef AnyClass)
+ || lam2.isJava && (formal1 isRef ObjectClass) && (formal2 isRef AnyClass)) &&
+ loop(rest1, rest2)
+ case nil =>
+ false
+ }
+ case nil =>
+ formals2.isEmpty
+ }
+ loop(lam1.paramInfos, lam2.paramInfos)
+ }
// Type equality =:=
@@ -1216,7 +1216,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
/** Form a normalized conjunction of two types.
* Note: For certain types, `&` is distributed inside the type. This holds for
* all types which are not value types (e.g. TypeBounds, ClassInfo,
- * ExprType, MethodType, PolyType). Also, when forming an `&`,
+ * ExprType, LambdaType). Also, when forming an `&`,
* instantiated TypeVars are dereferenced and annotations are stripped.
* Finally, refined types with the same refined name are
* opportunistically merged.
@@ -1245,7 +1245,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
/** Form a normalized conjunction of two types.
* Note: For certain types, `|` is distributed inside the type. This holds for
* all types which are not value types (e.g. TypeBounds, ClassInfo,
- * ExprType, MethodType, PolyType). Also, when forming an `|`,
+ * ExprType, LambdaType). Also, when forming an `|`,
* instantiated TypeVars are dereferenced and annotations are stripped.
*
* Sometimes, the disjunction of two types cannot be formed because
@@ -1276,20 +1276,20 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
val tparams2 = tp2.typeParams
if (tparams1.isEmpty)
if (tparams2.isEmpty) op(tp1, tp2)
- else original(tp1, tp2.appliedTo(tp2.typeParams.map(_.paramBoundsAsSeenFrom(tp2))))
+ else original(tp1, tp2.appliedTo(tp2.typeParams.map(_.paramInfoAsSeenFrom(tp2))))
else if (tparams2.isEmpty)
- original(tp1.appliedTo(tp1.typeParams.map(_.paramBoundsAsSeenFrom(tp1))), tp2)
+ original(tp1.appliedTo(tp1.typeParams.map(_.paramInfoAsSeenFrom(tp1))), tp2)
else
- PolyType(
- paramNames = tpnme.syntheticTypeParamNames(tparams1.length),
- variances = (tparams1, tparams2).zipped.map((tparam1, tparam2) =>
- (tparam1.paramVariance + tparam2.paramVariance) / 2))(
- paramBoundsExp = tl => (tparams1, tparams2).zipped.map((tparam1, tparam2) =>
- tl.lifted(tparams1, tparam1.paramBoundsAsSeenFrom(tp1)).bounds &
- tl.lifted(tparams2, tparam2.paramBoundsAsSeenFrom(tp2)).bounds),
+ HKTypeLambda(
+ paramNames = (HKTypeLambda.syntheticParamNames(tparams1.length), tparams1, tparams2)
+ .zipped.map((pname, tparam1, tparam2) =>
+ pname.withVariance((tparam1.paramVariance + tparam2.paramVariance) / 2)))(
+ paramInfosExp = tl => (tparams1, tparams2).zipped.map((tparam1, tparam2) =>
+ tl.integrate(tparams1, tparam1.paramInfoAsSeenFrom(tp1)).bounds &
+ tl.integrate(tparams2, tparam2.paramInfoAsSeenFrom(tp2)).bounds),
resultTypeExp = tl =>
- original(tl.lifted(tparams1, tp1).appliedTo(tl.paramRefs),
- tl.lifted(tparams2, tp2).appliedTo(tl.paramRefs)))
+ original(tl.integrate(tparams1, tp1).appliedTo(tl.paramRefs),
+ tl.integrate(tparams2, tp2).appliedTo(tl.paramRefs)))
}
/** Try to distribute `&` inside type, detect and handle conflicts
@@ -1392,8 +1392,8 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
case tp2: MethodType =>
def asGoodParams(formals1: List[Type], formals2: List[Type]) =
(formals2 corresponds formals1)(isSubTypeWhenFrozen)
- asGoodParams(tp1.paramTypes, tp2.paramTypes) &&
- (!asGoodParams(tp2.paramTypes, tp1.paramTypes) ||
+ asGoodParams(tp1.paramInfos, tp2.paramInfos) &&
+ (!asGoodParams(tp2.paramInfos, tp1.paramInfos) ||
isAsGood(tp1.resultType, tp2.resultType))
case _ =>
false
@@ -1424,7 +1424,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
def showGoal(tp1: Type, tp2: Type)(implicit ctx: Context) = {
println(ex"assertion failure for $tp1 <:< $tp2, frozen = $frozenConstraint")
def explainPoly(tp: Type) = tp match {
- case tp: PolyParam => ctx.echo(s"polyparam ${tp.show} found in ${tp.binder.show}")
+ case tp: TypeParamRef => ctx.echo(s"TypeParamRef ${tp.show} found in ${tp.binder.show}")
case tp: TypeRef if tp.symbol.exists => ctx.echo(s"typeref ${tp.show} found in ${tp.symbol.owner.show}")
case tp: TypeVar => ctx.echo(s"typevar ${tp.show}, origin = ${tp.origin}")
case _ => ctx.echo(s"${tp.show} is a ${tp.getClass}")
@@ -1503,7 +1503,7 @@ class ExplainingTypeComparer(initctx: Context) extends TypeComparer(initctx) {
super.glb(tp1, tp2)
}
- override def addConstraint(param: PolyParam, bound: Type, fromBelow: Boolean): Boolean =
+ override def addConstraint(param: TypeParamRef, bound: Type, fromBelow: Boolean): Boolean =
traceIndented(i"add constraint $param ${if (fromBelow) ">:" else "<:"} $bound $frozenConstraint, constraint = ${ctx.typerState.constraint}") {
super.addConstraint(param, bound, fromBelow)
}
diff --git a/compiler/src/dotty/tools/dotc/core/TypeErasure.scala b/compiler/src/dotty/tools/dotc/core/TypeErasure.scala
index fe3396fcb..f35752644 100644
--- a/compiler/src/dotty/tools/dotc/core/TypeErasure.scala
+++ b/compiler/src/dotty/tools/dotc/core/TypeErasure.scala
@@ -28,7 +28,7 @@ import scala.annotation.tailrec
* WildcardType
* ErrorType
*
- * only for isInstanceOf, asInstanceOf: PolyType, PolyParam, TypeBounds
+ * only for isInstanceOf, asInstanceOf: PolyType, TypeParamRef, TypeBounds
*
*/
object TypeErasure {
@@ -55,7 +55,7 @@ object TypeErasure {
case ThisType(tref) =>
isErasedType(tref)
case tp: MethodType =>
- tp.paramTypes.forall(isErasedType) && isErasedType(tp.resultType)
+ tp.paramInfos.forall(isErasedType) && isErasedType(tp.resultType)
case tp @ ClassInfo(pre, _, parents, decls, _) =>
isErasedType(pre) && parents.forall(isErasedType) //&& decls.forall(sym => isErasedType(sym.info)) && isErasedType(tp.selfType)
case NoType | NoPrefix | WildcardType | _: ErrorType | SuperType(_, _) =>
@@ -176,7 +176,7 @@ object TypeErasure {
val erase = erasureFn(isJava, semiEraseVCs, sym.isConstructor, wildcardOK = false)
def eraseParamBounds(tp: PolyType): Type =
- tp.derivedPolyType(
+ tp.derivedLambdaType(
tp.paramNames, tp.paramNames map (Function.const(TypeBounds.upper(defn.ObjectType))), tp.resultType)
if (defn.isPolymorphicAfterErasure(sym)) eraseParamBounds(sym.info.asInstanceOf[PolyType])
@@ -186,7 +186,7 @@ object TypeErasure {
case einfo: MethodType =>
if (sym.isGetter && einfo.resultType.isRef(defn.UnitClass))
MethodType(Nil, defn.BoxedUnitType)
- else if (sym.isAnonymousFunction && einfo.paramTypes.length > MaxImplementedFunctionArity)
+ else if (sym.isAnonymousFunction && einfo.paramInfos.length > MaxImplementedFunctionArity)
MethodType(nme.ALLARGS :: Nil, JavaArrayType(defn.ObjectType) :: Nil, einfo.resultType)
else
einfo
@@ -204,7 +204,7 @@ object TypeErasure {
!tp.symbol.isClass &&
!tp.derivesFrom(defn.ObjectClass) &&
!tp.symbol.is(JavaDefined)
- case tp: PolyParam =>
+ case tp: TypeParamRef =>
!tp.derivesFrom(defn.ObjectClass) &&
!tp.binder.resultType.isInstanceOf[JavaMethodType]
case tp: TypeAlias => isUnboundedGeneric(tp.alias)
@@ -304,7 +304,7 @@ object TypeErasure {
case _: ClassInfo => true
case _ => false
}
- case tp: PolyParam => false
+ case tp: TypeParamRef => false
case tp: TypeProxy => hasStableErasure(tp.superType)
case tp: AndOrType => hasStableErasure(tp.tp1) && hasStableErasure(tp.tp2)
case _ => false
@@ -382,13 +382,15 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean
case tp: MethodType =>
def paramErasure(tpToErase: Type) =
erasureFn(tp.isJava, semiEraseVCs, isConstructor, wildcardOK)(tpToErase)
- val formals = tp.paramTypes.mapConserve(paramErasure)
+ val formals = tp.paramInfos.mapConserve(paramErasure)
eraseResult(tp.resultType) match {
case rt: MethodType =>
- tp.derivedMethodType(tp.paramNames ++ rt.paramNames, formals ++ rt.paramTypes, rt.resultType)
+ tp.derivedLambdaType(tp.paramNames ++ rt.paramNames, formals ++ rt.paramInfos, rt.resultType)
case rt =>
- tp.derivedMethodType(tp.paramNames, formals, rt)
+ tp.derivedLambdaType(tp.paramNames, formals, rt)
}
+ case tp: PolyType =>
+ this(tp.resultType)
case tp @ ClassInfo(pre, cls, classParents, decls, _) =>
if (cls is Package) tp
else {
@@ -517,6 +519,8 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean
if (inst.exists) sigName(inst) else tpnme.Uninstantiated
case tp: TypeProxy =>
sigName(tp.underlying)
+ case tp: PolyType =>
+ sigName(tp.resultType)
case _: ErrorType | WildcardType =>
tpnme.WILDCARD
case tp: WildcardType =>
diff --git a/compiler/src/dotty/tools/dotc/core/TypeOps.scala b/compiler/src/dotty/tools/dotc/core/TypeOps.scala
index 3d2906320..9593bfe93 100644
--- a/compiler/src/dotty/tools/dotc/core/TypeOps.scala
+++ b/compiler/src/dotty/tools/dotc/core/TypeOps.scala
@@ -157,7 +157,7 @@ trait TypeOps { this: Context => // TODO: Make standalone object.
tp2
case tp1 => tp1
}
- case tp: PolyParam =>
+ case tp: TypeParamRef =>
typerState.constraint.typeVarOfParam(tp) orElse tp
case _: ThisType | _: BoundType | NoPrefix =>
tp
diff --git a/compiler/src/dotty/tools/dotc/core/TyperState.scala b/compiler/src/dotty/tools/dotc/core/TyperState.scala
index 206438d86..b33b3aa29 100644
--- a/compiler/src/dotty/tools/dotc/core/TyperState.scala
+++ b/compiler/src/dotty/tools/dotc/core/TyperState.scala
@@ -42,7 +42,7 @@ class TyperState(r: Reporter) extends DotClass with Showable {
*/
def instType(tvar: TypeVar)(implicit ctx: Context): Type = constraint.entry(tvar.origin) match {
case _: TypeBounds => NoType
- case tp: PolyParam =>
+ case tp: TypeParamRef =>
var tvar1 = constraint.typeVarOfParam(tp)
if (tvar1.exists) tvar1 else tp
case tp => tp
@@ -155,14 +155,14 @@ extends TyperState(r) {
}
override def gc()(implicit ctx: Context): Unit = {
- val toCollect = new mutable.ListBuffer[PolyType]
+ val toCollect = new mutable.ListBuffer[TypeLambda]
constraint foreachTypeVar { tvar =>
if (!tvar.inst.exists) {
val inst = instType(tvar)
if (inst.exists && (tvar.owningState eq this)) {
tvar.inst = inst
- val poly = tvar.origin.binder
- if (constraint.isRemovable(poly)) toCollect += poly
+ val lam = tvar.origin.binder
+ if (constraint.isRemovable(lam)) toCollect += lam
}
}
}
diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala
index c80107f93..83fb70aa1 100644
--- a/compiler/src/dotty/tools/dotc/core/Types.scala
+++ b/compiler/src/dotty/tools/dotc/core/Types.scala
@@ -54,10 +54,10 @@ object Types {
* | | +--- ThisType
* | | +--- SuperType
* | | +--- ConstantType
- * | | +--- MethodParam
+ * | | +--- TermParamRef
* | | +----RecThis
* | | +--- SkolemType
- * | +- PolyParam
+ * | +- TypeParamRef
* | +- RefinedOrRecType -+-- RefinedType
* | | -+-- RecType
* | +- HKApply
@@ -65,12 +65,13 @@ object Types {
* | +- ExprType
* | +- AnnotatedType
* | +- TypeVar
- * | +- PolyType
+ * | +- HKTypeLambda
* |
* +- GroundType -+- AndType
* +- OrType
- * +- MethodType -----+- ImplicitMethodType
- * | +- JavaMethodType
+ * +- MethodOrPoly ---+-- PolyType
+ * +-- MethodType ---+- ImplicitMethodType
+ * | +- JavaMethodType
* +- ClassInfo
* |
* +- NoType
@@ -103,7 +104,7 @@ object Types {
final def isValueType: Boolean = this.isInstanceOf[ValueType]
/** Is the is value type or type lambda? */
- final def isValueTypeOrLambda: Boolean = isValueType || this.isInstanceOf[PolyType]
+ final def isValueTypeOrLambda: Boolean = isValueType || this.isInstanceOf[TypeLambda]
/** Does this type denote a stable reference (i.e. singleton type)? */
@tailrec final def isStable(implicit ctx: Context): Boolean = stripTypeVar match {
@@ -215,17 +216,15 @@ object Types {
/** Is this the type of a method that has a repeated parameter type as
* last parameter type?
*/
- def isVarArgsMethod(implicit ctx: Context): Boolean = this match {
- case tp: PolyType => tp.resultType.isVarArgsMethod
- case mt: MethodType => mt.paramTypes.nonEmpty && mt.paramTypes.last.isRepeatedParam
+ def isVarArgsMethod(implicit ctx: Context): Boolean = stripPoly match {
+ case mt: MethodType => mt.paramInfos.nonEmpty && mt.paramInfos.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 {
+ def isNullaryMethod(implicit ctx: Context): Boolean = stripPoly match {
case MethodType(Nil) => true
- case tp: PolyType => tp.resultType.isNullaryMethod
case _ => false
}
@@ -443,10 +442,10 @@ object Types {
case tp: TermRef =>
go (tp.underlying match {
case mt: MethodType
- if mt.paramTypes.isEmpty && (tp.symbol is Stable) => mt.resultType
+ if mt.paramInfos.isEmpty && (tp.symbol is Stable) => mt.resultType
case tp1 => tp1
})
- case tp: PolyParam =>
+ case tp: TypeParamRef =>
goParam(tp)
case tp: RecType =>
goRec(tp)
@@ -541,9 +540,9 @@ object Types {
}
def goApply(tp: HKApply) = tp.tycon match {
- case tl: PolyType =>
+ case tl: HKTypeLambda =>
go(tl.resType).mapInfo(info =>
- tl.derivedLambdaAbstraction(tl.paramNames, tl.paramBounds, info).appliedTo(tp.args))
+ tl.derivedLambdaAbstraction(tl.paramNames, tl.paramInfos, info).appliedTo(tp.args))
case _ =>
go(tp.superType)
}
@@ -563,7 +562,7 @@ object Types {
// loadClassWithPrivateInnerAndSubSelf in ShowClassTests
go(tp.cls.typeRef) orElse d
}
- def goParam(tp: PolyParam) = {
+ def goParam(tp: TypeParamRef) = {
val next = tp.underlying
ctx.typerState.constraint.entry(tp) match {
case bounds: TypeBounds if bounds ne next =>
@@ -814,6 +813,12 @@ object Types {
*/
def stripAnnots(implicit ctx: Context): Type = this
+ /** Strip PolyType prefix */
+ def stripPoly(implicit ctx: Context): Type = this match {
+ case tp: PolyType => tp.resType.stripPoly
+ case _ => this
+ }
+
/** Widen from singleton type to its underlying non-singleton
* base type by applying one or more `underlying` dereferences,
* Also go from => T to T.
@@ -1088,43 +1093,38 @@ object Types {
}
/** The parameter types of a PolyType or MethodType, Empty list for others */
- final def paramTypess(implicit ctx: Context): List[List[Type]] = this match {
- case mt: MethodType => mt.paramTypes :: mt.resultType.paramTypess
- case pt: PolyType => pt.resultType.paramTypess
+ final def paramInfoss(implicit ctx: Context): List[List[Type]] = stripPoly match {
+ case mt: MethodType => mt.paramInfos :: mt.resultType.paramInfoss
case _ => Nil
}
/** The parameter names of a PolyType or MethodType, Empty list for others */
- final def paramNamess(implicit ctx: Context): List[List[TermName]] = this match {
+ final def paramNamess(implicit ctx: Context): List[List[TermName]] = stripPoly match {
case mt: MethodType => mt.paramNames :: mt.resultType.paramNamess
- case pt: PolyType => pt.resultType.paramNamess
case _ => Nil
}
/** The parameter types in the first parameter section of a generic type or MethodType, Empty list for others */
- @tailrec final def firstParamTypes(implicit ctx: Context): List[Type] = this match {
- case mt: MethodType => mt.paramTypes
- case pt: PolyType => pt.resultType.firstParamTypes
+ final def firstParamTypes(implicit ctx: Context): List[Type] = stripPoly match {
+ case mt: MethodType => mt.paramInfos
case _ => Nil
}
/** Is this either not a method at all, or a parameterless method? */
- @tailrec final def isParameterless(implicit ctx: Context): Boolean = this match {
+ final def isParameterless(implicit ctx: Context): Boolean = stripPoly match {
case mt: MethodType => false
- case pt: PolyType => pt.resultType.isParameterless
case _ => true
}
- /** The resultType of a PolyType, MethodType, or ExprType, the type itself for others */
+ /** The resultType of a LambdaType, or ExprType, the type itself for others */
def resultType(implicit ctx: Context): Type = this
/** The final result type of a PolyType, MethodType, or ExprType, after skipping
* all parameter sections, the type itself for all others.
*/
- def finalResultType(implicit ctx: Context): Type = resultType match {
+ def finalResultType(implicit ctx: Context): Type = resultType.stripPoly match {
case mt: MethodType => mt.resultType.finalResultType
- case pt: PolyType => pt.resultType.finalResultType
case _ => resultType
}
@@ -1180,8 +1180,8 @@ object Types {
final def substDealias(from: List[Symbol], to: List[Type])(implicit ctx: Context): Type =
ctx.substDealias(this, from, to, null)
- /** Substitute all types of the form `PolyParam(from, N)` by
- * `PolyParam(to, N)`.
+ /** Substitute all types of the form `TypeParamRef(from, N)` by
+ * `TypeParamRef(to, N)`.
*/
final def subst(from: BindingType, to: BindingType)(implicit ctx: Context): Type =
ctx.subst(this, from, to, null)
@@ -1199,7 +1199,7 @@ object Types {
ctx.substRecThis(this, binder, tp, null)
/** Substitute a bound type by some other type */
- final def substParam(from: ParamType, to: Type)(implicit ctx: Context): Type =
+ final def substParam(from: ParamRef, to: Type)(implicit ctx: Context): Type =
ctx.substParam(this, from, to, null)
/** Substitute bound types by some other types */
@@ -1220,7 +1220,7 @@ object Types {
*/
def toFunctionType(dropLast: Int = 0)(implicit ctx: Context): Type = this match {
case mt: MethodType if !mt.isDependent || ctx.mode.is(Mode.AllowDependentFunctions) =>
- val formals1 = if (dropLast == 0) mt.paramTypes else mt.paramTypes dropRight dropLast
+ val formals1 = if (dropLast == 0) mt.paramInfos else mt.paramInfos dropRight dropLast
defn.FunctionOf(
formals1 mapConserve (_.underlyingIfRepeated(mt.isJava)), mt.resultType, mt.isImplicit && !ctx.erasedTypes)
}
@@ -1360,7 +1360,7 @@ object Types {
}
/** A marker trait for types that bind other types that refer to them.
- * Instances are: PolyType, MethodType, RefinedType.
+ * Instances are: LambdaType, RecType.
*/
trait BindingType extends Type
@@ -2280,7 +2280,7 @@ object Types {
if (tp1 eq tp2) tp1 else apply(tp1, tp2)
}
- // ----- Method types: MethodType/ExprType/PolyType -------------------------------
+ // ----- ExprType and LambdaTypes -----------------------------------
// Note: method types are cached whereas poly types are not. The reason
// is that most poly types are cyclic via poly params,
@@ -2315,20 +2315,126 @@ object Types {
}
}
- trait MethodOrPoly extends MethodicType
+ /** A by-name parameter type of the form `=> T`, or the type of a method with no parameter list. */
+ abstract case class ExprType(resType: Type)
+ extends CachedProxyType with TermType with MethodicType {
+ override def resultType(implicit ctx: Context): Type = resType
+ override def underlying(implicit ctx: Context): Type = resType
+ protected def computeSignature(implicit ctx: Context): Signature = resultSignature
+ def derivedExprType(resType: Type)(implicit ctx: Context) =
+ if (resType eq this.resType) this else ExprType(resType)
+ override def computeHash = doHash(resType)
+ }
- 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._
+ final class CachedExprType(resultType: Type) extends ExprType(resultType)
+
+ object ExprType {
+ def apply(resultType: Type)(implicit ctx: Context) = {
+ assertUnerased()
+ unique(new CachedExprType(resultType))
+ }
+ }
- def isJava = false
+ /** The lambda type square:
+ *
+ * LambdaType | TermLambda | TypeLambda
+ * -------------+-------------------+------------------
+ * HKLambda | HKTermLambda | HKTypeLambda
+ * MethodOrPoly | MethodType | PolyType
+ */
+ trait LambdaType extends BindingType with MethodicType { self =>
+ type ThisName <: Name
+ type PInfo <: Type
+ type This <: LambdaType{type PInfo = self.PInfo}
+
+ def paramNames: List[ThisName]
+ def paramInfos: List[PInfo]
+ def resType: Type
+ def newParamRef(n: Int): ParamRef
+
+ override def resultType(implicit ctx: Context) = resType
+
+ def isJava: Boolean = false
def isImplicit = false
- val paramTypes = paramTypesExp(this)
- private[core] val resType = resultTypeExp(this)
- assert(resType.exists)
+ def isDependent(implicit ctx: Context): Boolean
+ def isParamDependent(implicit ctx: Context): Boolean
+
+ final def isTermLambda = isInstanceOf[TermLambda]
+ final def isTypeLambda = isInstanceOf[TypeLambda]
+ final def isHigherKinded = isInstanceOf[TypeProxy]
+
+ lazy val paramRefs: List[ParamRef] = paramNames.indices.toList.map(newParamRef)
+
+ protected def computeSignature(implicit ctx: Context) = resultSignature
+
+ final def instantiate(argTypes: => List[Type])(implicit ctx: Context): Type =
+ if (isDependent) resultType.substParams(this, argTypes)
+ else resultType
+
+ def companion: LambdaTypeCompanion[ThisName, PInfo, This]
+
+ /** The type `[tparams := paramRefs] tp`, where `tparams` can be
+ * either a list of type parameter symbols or a list of lambda parameters
+ */
+ def integrate(tparams: List[ParamInfo], tp: Type)(implicit ctx: Context): Type =
+ tparams match {
+ case LambdaParam(lam, _) :: _ => tp.subst(lam, this)
+ case tparams: List[Symbol @unchecked] => tp.subst(tparams, paramRefs)
+ }
+
+ final def derivedLambdaType(paramNames: List[ThisName] = this.paramNames,
+ paramInfos: List[PInfo] = this.paramInfos,
+ resType: Type = this.resType)(implicit ctx: Context) =
+ if ((paramNames eq this.paramNames) && (paramInfos eq this.paramInfos) && (resType eq this.resType)) this
+ else newLikeThis(paramNames, paramInfos, resType)
+
+ final def newLikeThis(paramNames: List[ThisName], paramInfos: List[PInfo], resType: Type)(implicit ctx: Context): This =
+ companion(paramNames)(
+ x => paramInfos.mapConserve(_.subst(this, x).asInstanceOf[PInfo]),
+ x => resType.subst(this, x))
+
+ protected def prefixString: String
+ final override def toString = s"$prefixString($paramNames, $paramInfos, $resType)"
+ }
+
+ abstract class HKLambda extends CachedProxyType with LambdaType {
+ final override def underlying(implicit ctx: Context) = resType
+
+ final override def computeHash = doHash(paramNames, resType, paramInfos)
+
+ // Defined here instead of in LambdaType for efficiency
+ final override def equals(that: Any) = that match {
+ case that: HKLambda =>
+ this.paramNames == that.paramNames &&
+ this.paramInfos == that.paramInfos &&
+ this.resType == that.resType &&
+ (this.companion eq that.companion)
+ case _ =>
+ false
+ }
+ }
+
+ abstract class MethodOrPoly extends CachedGroundType with LambdaType with TermType {
+ final override def computeHash = doHash(paramNames, resType, paramInfos)
+
+ // Defined here instead of in LambdaType for efficiency
+ final override def equals(that: Any) = that match {
+ case that: MethodOrPoly =>
+ this.paramNames == that.paramNames &&
+ this.paramInfos == that.paramInfos &&
+ this.resType == that.resType &&
+ (this.companion eq that.companion)
+ case _ =>
+ false
+ }
+ }
+
+ trait TermLambda extends LambdaType { thisLambdaType =>
+ import DepStatus._
+ type ThisName = TermName
+ type PInfo = Type
+ type This <: TermLambda
override def resultType(implicit ctx: Context): Type =
if (dependencyStatus == FalseDeps) { // dealias all false dependencies
@@ -2347,8 +2453,8 @@ object Types {
}
else resType
- var myDependencyStatus: DependencyStatus = Unknown
- var myParamDependencyStatus: DependencyStatus = Unknown
+ private var myDependencyStatus: DependencyStatus = Unknown
+ private var myParamDependencyStatus: DependencyStatus = Unknown
private def depStatus(initial: DependencyStatus, tp: Type)(implicit ctx: Context): DependencyStatus = {
def combine(x: DependencyStatus, y: DependencyStatus) = {
@@ -2361,7 +2467,7 @@ object Types {
if (status == TrueDeps) status
else
tp match {
- case MethodParam(`thisMethodType`, _) => TrueDeps
+ case TermParamRef(`thisLambdaType`, _) => TrueDeps
case tp: TypeRef =>
val status1 = foldOver(status, tp)
tp.info match { // follow type alias to avoid dependency
@@ -2401,8 +2507,8 @@ object Types {
if (myParamDependencyStatus != Unknown) myParamDependencyStatus
else {
val result =
- if (paramTypes.isEmpty) NoDeps
- else (NoDeps /: paramTypes.tail)(depStatus(_, _))
+ if (paramInfos.isEmpty) NoDeps
+ else (NoDeps /: paramInfos.tail)(depStatus(_, _))
if ((result & Provisional) == 0) myParamDependencyStatus = result
(result & StatusMask).toByte
}
@@ -2418,75 +2524,90 @@ object Types {
*/
def isParamDependent(implicit ctx: Context): Boolean = paramDependencyStatus == TrueDeps
- protected def computeSignature(implicit ctx: Context): Signature =
- resultSignature.prepend(paramTypes, isJava)
+ def newParamRef(n: Int) = TermParamRef(this, n)
+ }
- def derivedMethodType(paramNames: List[TermName] = this.paramNames,
- paramTypes: List[Type] = this.paramTypes,
- 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)(paramTypesFn, resTypeFn)
- else if (isImplicit) ImplicitMethodType(paramNames)(paramTypesFn, resTypeFn)
- else MethodType(paramNames)(paramTypesFn, resTypeFn)
- }
+ abstract case class MethodType(paramNames: List[TermName])(
+ paramInfosExp: MethodType => List[Type],
+ resultTypeExp: MethodType => Type)
+ extends MethodOrPoly with TermLambda with NarrowCached { thisMethodType =>
+ import MethodType._
- def instantiate(argTypes: => List[Type])(implicit ctx: Context): Type =
- if (isDependent) resultType.substParams(this, argTypes)
- else resultType
+ type This = MethodType
- override def equals(that: Any) = that match {
- case that: MethodType =>
- this.paramNames == that.paramNames &&
- this.paramTypes == that.paramTypes &&
- this.resType == that.resType
- case _ =>
- false
- }
+ val paramInfos = paramInfosExp(this)
+ val resType = resultTypeExp(this)
+ assert(resType.exists)
- override def computeHash = doHash(paramNames, resType, paramTypes)
+ override def computeSignature(implicit ctx: Context): Signature =
+ resultSignature.prepend(paramInfos, isJava)
protected def prefixString = "MethodType"
- override def toString = s"$prefixString($paramNames, $paramTypes, $resType)"
}
- 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 CachedMethodType(paramNames: List[TermName])(paramInfosExp: MethodType => List[Type], resultTypeExp: MethodType => Type)
+ extends MethodType(paramNames)(paramInfosExp, resultTypeExp) {
+ def companion = MethodType
}
- final class JavaMethodType(paramNames: List[TermName])(paramTypesExp: MethodType => List[Type], resultTypeExp: MethodType => Type)
- extends MethodType(paramNames)(paramTypesExp, resultTypeExp) {
+ final class JavaMethodType(paramNames: List[TermName])(paramInfosExp: MethodType => List[Type], resultTypeExp: MethodType => Type)
+ extends MethodType(paramNames)(paramInfosExp, resultTypeExp) {
+ def companion = JavaMethodType
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])(paramTypesExp: MethodType => List[Type], resultTypeExp: MethodType => Type)
- extends MethodType(paramNames)(paramTypesExp, resultTypeExp) {
+ final class ImplicitMethodType(paramNames: List[TermName])(paramInfosExp: MethodType => List[Type], resultTypeExp: MethodType => Type)
+ extends MethodType(paramNames)(paramInfosExp, resultTypeExp) {
+ def companion = ImplicitMethodType
override def isImplicit = true
- override def equals(that: Any) = super.equals(that) && that.isInstanceOf[ImplicitMethodType]
- override def computeHash = addDelta(super.computeHash, 2)
override protected def prefixString = "ImplicitMethodType"
}
- abstract class MethodTypeCompanion {
- 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)
- def apply(paramTypes: List[Type])(resultTypeExp: MethodType => Type)(implicit ctx: Context): MethodType =
- 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)
+ abstract class LambdaTypeCompanion[N <: Name, PInfo <: Type, LT <: LambdaType] {
+ def syntheticParamName(n: Int): N
+
+ @sharable private val memoizedNames = new mutable.HashMap[Int, List[N]]
+ def syntheticParamNames(n: Int): List[N] = synchronized {
+ memoizedNames.getOrElseUpdate(n, (0 until n).map(syntheticParamName).toList)
+ }
+
+ def apply(paramNames: List[N])(paramInfosExp: LT => List[PInfo], resultTypeExp: LT => Type)(implicit ctx: Context): LT
+ def apply(paramNames: List[N], paramInfos: List[PInfo], resultType: Type)(implicit ctx: Context): LT =
+ apply(paramNames)(_ => paramInfos, _ => resultType)
+ def apply(paramInfos: List[PInfo])(resultTypeExp: LT => Type)(implicit ctx: Context): LT =
+ apply(syntheticParamNames(paramInfos.length))(_ => paramInfos, resultTypeExp)
+ def apply(paramInfos: List[PInfo], resultType: Type)(implicit ctx: Context): LT =
+ apply(syntheticParamNames(paramInfos.length), paramInfos, resultType)
+
+ protected def paramName(param: ParamInfo.Of[N])(implicit ctx: Context): N =
+ param.paramName
+
+ def fromParams[PI <: ParamInfo.Of[N]](params: List[PI], resultType: Type)(implicit ctx: Context): Type =
+ if (params.isEmpty) resultType
+ else apply(params.map(paramName))(
+ tl => params.map(param => tl.integrate(params, param.paramInfo).asInstanceOf[PInfo]),
+ tl => tl.integrate(params, resultType))
+ }
+
+ abstract class TermLambdaCompanion[LT <: TermLambda]
+ extends LambdaTypeCompanion[TermName, Type, LT] {
+ def syntheticParamName(n: Int) = nme.syntheticParamName(n)
+ }
+
+ abstract class TypeLambdaCompanion[LT <: TypeLambda]
+ extends LambdaTypeCompanion[TypeName, TypeBounds, LT] {
+ def syntheticParamName(n: Int) = tpnme.syntheticTypeParamName(n)
+ }
+
+ abstract class MethodTypeCompanion extends TermLambdaCompanion[MethodType] {
/** Produce method type from parameter symbols, with special mappings for repeated
- * and inline parameters.
+ * and inline parameters:
+ * - replace @repeated annotations on Seq or Array types by <repeated> types
+ * - add @inlineParam to inline call-by-value parameters
*/
def fromSymbols(params: List[Symbol], resultType: Type)(implicit ctx: Context) = {
- /** Replace @repeated annotations on Seq or Array types by <repeated> types */
def translateRepeated(tp: Type): Type = tp match {
case tp @ ExprType(tp1) => tp.derivedExprType(translateRepeated(tp1))
case AnnotatedType(tp, annot) if annot matches defn.RepeatedAnnot =>
@@ -2496,27 +2617,25 @@ object Types {
case tp =>
tp
}
- /** Add @inlineParam to inline call-by-value parameters */
def translateInline(tp: Type): Type = tp match {
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 = {
+ def paramInfo(param: Symbol) = {
val paramType = translateRepeated(param.info)
if (param.is(Inline)) translateInline(paramType) else paramType
}
+
apply(params.map(_.name.asTermName))(
- mt => params.map(param => integrate(paramInfo(param), mt)),
- mt => integrate(resultType, mt))
+ tl => params.map(p => tl.integrate(params, paramInfo(p))),
+ tl => tl.integrate(params, resultType))
}
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)
+ for ((paramInfo, idx) <- mt.paramInfos.zipWithIndex)
+ paramInfo.foreachPart {
+ case TermParamRef(`mt`, j) => assert(j < idx, mt)
case _ =>
}
mt
@@ -2524,114 +2643,97 @@ object Types {
}
object MethodType extends MethodTypeCompanion {
- 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
- private final val NoDeps: DependencyStatus = 1 // no dependent parameters found
- private final val FalseDeps: DependencyStatus = 2 // all dependent parameters are prefixes of non-depended alias types
- private final val TrueDeps: DependencyStatus = 3 // some truly dependent parameters exist
- private final val StatusMask: DependencyStatus = 3 // the bits indicating actual dependency status
- private final val Provisional: DependencyStatus = 4 // set if dependency status can still change due to type variable instantiations
+ def apply(paramNames: List[TermName])(paramInfosExp: MethodType => List[Type], resultTypeExp: MethodType => Type)(implicit ctx: Context): MethodType =
+ checkValid(unique(new CachedMethodType(paramNames)(paramInfosExp, resultTypeExp)))
}
object JavaMethodType extends MethodTypeCompanion {
- def apply(paramNames: List[TermName])(paramTypesExp: MethodType => List[Type], resultTypeExp: MethodType => Type)(implicit ctx: Context): MethodType =
- unique(new JavaMethodType(paramNames)(paramTypesExp, resultTypeExp))
+ def apply(paramNames: List[TermName])(paramInfosExp: MethodType => List[Type], resultTypeExp: MethodType => Type)(implicit ctx: Context): MethodType =
+ unique(new JavaMethodType(paramNames)(paramInfosExp, resultTypeExp))
}
object ImplicitMethodType extends MethodTypeCompanion {
- def apply(paramNames: List[TermName])(paramTypesExp: MethodType => List[Type], resultTypeExp: MethodType => Type)(implicit ctx: Context): MethodType =
- checkValid(unique(new ImplicitMethodType(paramNames)(paramTypesExp, resultTypeExp)))
+ def apply(paramNames: List[TermName])(paramInfosExp: MethodType => List[Type], resultTypeExp: MethodType => Type)(implicit ctx: Context): MethodType =
+ checkValid(unique(new ImplicitMethodType(paramNames)(paramInfosExp, 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. */
- abstract case class ExprType(resType: Type)
- extends CachedProxyType with TermType with MethodicType {
- override def resultType(implicit ctx: Context): Type = resType
- override def underlying(implicit ctx: Context): Type = resType
- protected def computeSignature(implicit ctx: Context): Signature = resultSignature
- def derivedExprType(resType: Type)(implicit ctx: Context) =
- if (resType eq this.resType) this else ExprType(resType)
- override def computeHash = doHash(resType)
+ Some((mt.paramNames, mt.paramInfos, mt.resultType))
}
- final class CachedExprType(resultType: Type) extends ExprType(resultType)
-
- object ExprType {
- def apply(resultType: Type)(implicit ctx: Context) = {
- assertUnerased()
- unique(new CachedExprType(resultType))
- }
- }
-
- /** A type lambda of the form `[v_0 X_0, ..., v_n X_n] => T` */
- class PolyType(val paramNames: List[TypeName], val variances: List[Int])(
- paramBoundsExp: PolyType => List[TypeBounds], resultTypeExp: PolyType => Type)
- extends CachedProxyType with BindingType with MethodOrPoly {
-
- /** The bounds of the type parameters */
- val paramBounds: List[TypeBounds] = paramBoundsExp(this)
-
- /** The result type of a PolyType / body of a type lambda */
- val resType: Type = resultTypeExp(this)
-
- assert(resType.isInstanceOf[TermType], this)
- assert(paramNames.nonEmpty)
-
- protected def computeSignature(implicit ctx: Context) = resultSignature
+ trait TypeLambda extends LambdaType {
+ type ThisName = TypeName
+ type PInfo = TypeBounds
+ type This <: TypeLambda
- def isPolymorphicMethodType: Boolean = resType match {
- case _: MethodType => true
- case _ => false
- }
+ def isDependent(implicit ctx: Context): Boolean = true
+ def isParamDependent(implicit ctx: Context): Boolean = true
- /** PolyParam references to all type parameters of this type */
- lazy val paramRefs: List[PolyParam] = paramNames.indices.toList.map(PolyParam(this, _))
+ def newParamRef(n: Int) = TypeParamRef(this, n)
lazy val typeParams: List[LambdaParam] =
paramNames.indices.toList.map(new LambdaParam(this, _))
- override def resultType(implicit ctx: Context) = resType
- override def underlying(implicit ctx: Context) = resType
-
- /** Instantiate result type by substituting parameters with given arguments */
- final def instantiate(argTypes: List[Type])(implicit ctx: Context): Type =
- resultType.substParams(this, argTypes)
-
/** Instantiate parameter bounds by substituting parameters with given arguments */
- final def instantiateBounds(argTypes: List[Type])(implicit ctx: Context): List[TypeBounds] =
- paramBounds.mapConserve(_.substParams(this, argTypes).bounds)
-
- def newLikeThis(paramNames: List[TypeName], paramBounds: List[TypeBounds], resType: Type)(implicit ctx: Context): PolyType =
- PolyType.apply(paramNames, variances)(
- x => paramBounds mapConserve (_.subst(this, x).bounds),
- x => resType.subst(this, x))
-
- def derivedPolyType(paramNames: List[TypeName] = this.paramNames,
- paramBounds: List[TypeBounds] = this.paramBounds,
- resType: Type = this.resType)(implicit ctx: Context) =
- if ((paramNames eq this.paramNames) && (paramBounds eq this.paramBounds) && (resType eq this.resType)) this
- else newLikeThis(paramNames, paramBounds, resType)
+ final def instantiateBounds(argTypes: List[Type])(implicit ctx: Context): List[Type] =
+ paramInfos.mapConserve(_.substParams(this, argTypes))
- def derivedLambdaAbstraction(paramNames: List[TypeName], paramBounds: List[TypeBounds], resType: Type)(implicit ctx: Context): Type =
+ def derivedLambdaAbstraction(paramNames: List[TypeName], paramInfos: List[TypeBounds], resType: Type)(implicit ctx: Context): Type =
resType match {
case resType @ TypeAlias(alias) =>
- resType.derivedTypeAlias(newLikeThis(paramNames, paramBounds, alias))
+ resType.derivedTypeAlias(newLikeThis(paramNames, paramInfos, alias))
case resType @ TypeBounds(lo, hi) =>
resType.derivedTypeBounds(
- if (lo.isRef(defn.NothingClass)) lo else newLikeThis(paramNames, paramBounds, lo),
- newLikeThis(paramNames, paramBounds, hi))
+ if (lo.isRef(defn.NothingClass)) lo else newLikeThis(paramNames, paramInfos, lo),
+ newLikeThis(paramNames, paramInfos, hi))
case _ =>
- derivedPolyType(paramNames, paramBounds, resType)
+ derivedLambdaType(paramNames, paramInfos, resType)
}
+ }
+
+ /** A type lambda of the form `[X_0 B_0, ..., X_n B_n] => T`
+ * Variances are encoded in parameter names. A name starting with `+`
+ * designates a covariant parameter, a name starting with `-` designates
+ * a contravariant parameter, and every other name designates a non-variant parameter.
+ *
+ * @param paramNames The names `X_0`, ..., `X_n`
+ * @param paramInfosExp A function that, given the polytype itself, returns the
+ * parameter bounds `B_1`, ..., `B_n`
+ * @param resultTypeExp A function that, given the polytype itself, returns the
+ * result type `T`.
+ */
+ class HKTypeLambda(val paramNames: List[TypeName])(
+ paramInfosExp: HKTypeLambda => List[TypeBounds], resultTypeExp: HKTypeLambda => Type)
+ extends HKLambda with TypeLambda {
+ type This = HKTypeLambda
+ def companion = HKTypeLambda
+
+ val paramInfos: List[TypeBounds] = paramInfosExp(this)
+ val resType: Type = resultTypeExp(this)
+
+ assert(resType.isInstanceOf[TermType], this)
+ assert(paramNames.nonEmpty)
+
+ protected def prefixString = "HKTypeLambda"
+ }
+
+ /** The type of a polymorphic method. It has the same form as HKTypeLambda,
+ * except it applies to terms and parameters do not have variances.
+ */
+ class PolyType(val paramNames: List[TypeName])(
+ paramInfosExp: PolyType => List[TypeBounds], resultTypeExp: PolyType => Type)
+ extends MethodOrPoly with TypeLambda {
+
+ type This = PolyType
+ def companion = PolyType
+
+ val paramInfos: List[TypeBounds] = paramInfosExp(this)
+ val resType: Type = resultTypeExp(this)
+
+ assert(resType.isInstanceOf[TermType], this)
+ assert(paramNames.nonEmpty)
/** Merge nested polytypes into one polytype. nested polytypes are normally not supported
* but can arise as temporary data structures.
@@ -2640,67 +2742,95 @@ object Types {
case that: PolyType =>
val shift = new TypeMap {
def apply(t: Type) = t match {
- case PolyParam(`that`, n) => PolyParam(that, n + paramNames.length)
+ case TypeParamRef(`that`, n) => TypeParamRef(that, n + paramNames.length)
case t => mapOver(t)
}
}
- PolyType(paramNames ++ that.paramNames, variances ++ that.variances)(
- x => this.paramBounds.mapConserve(_.subst(this, x).bounds) ++
- that.paramBounds.mapConserve(shift(_).subst(that, x).bounds),
+ PolyType(paramNames ++ that.paramNames)(
+ x => this.paramInfos.mapConserve(_.subst(this, x).bounds) ++
+ that.paramInfos.mapConserve(shift(_).subst(that, x).bounds),
x => shift(that.resultType).subst(that, x).subst(this, x))
case _ => this
}
- /** The type `[tparams := paramRefs] tp`, where `tparams` can be
- * either a list of type parameter symbols or a list of lambda parameters
- */
- def lifted(tparams: List[TypeParamInfo], tp: Type)(implicit ctx: Context): Type =
- tparams match {
- case LambdaParam(poly, _) :: _ => tp.subst(poly, this)
- case tparams: List[Symbol @unchecked] => tp.subst(tparams, paramRefs)
- }
+ protected def prefixString = "PolyType"
+ }
- override def equals(other: Any) = other match {
- case other: PolyType =>
- other.paramNames == this.paramNames &&
- other.paramBounds == this.paramBounds &&
- other.resType == this.resType &&
- other.variances == this.variances
- case _ => false
+ object HKTypeLambda extends TypeLambdaCompanion[HKTypeLambda] {
+ def apply(paramNames: List[TypeName])(
+ paramInfosExp: HKTypeLambda => List[TypeBounds],
+ resultTypeExp: HKTypeLambda => Type)(implicit ctx: Context): HKTypeLambda = {
+ unique(new HKTypeLambda(paramNames)(paramInfosExp, resultTypeExp))
}
- override def toString = s"PolyType($variances, $paramNames, $paramBounds, $resType)"
+ def unapply(tl: HKTypeLambda): Some[(List[LambdaParam], Type)] =
+ Some((tl.typeParams, tl.resType))
+
+ def any(n: Int)(implicit ctx: Context) =
+ apply(syntheticParamNames(n))(
+ pt => List.fill(n)(TypeBounds.empty), pt => defn.AnyType)
- override def computeHash = doHash(variances ::: paramNames, resType, paramBounds)
+ override def paramName(param: ParamInfo.Of[TypeName])(implicit ctx: Context): TypeName =
+ param.paramName.withVariance(param.paramVariance)
+
+ /** Distributes Lambda inside type bounds. Examples:
+ *
+ * type T[X] = U becomes type T = [X] -> U
+ * type T[X] <: U becomes type T >: Nothign <: ([X] -> U)
+ * type T[X] >: L <: U becomes type T >: ([X] -> L) <: ([X] -> U)
+ */
+ override def fromParams[PI <: ParamInfo.Of[TypeName]](params: List[PI], resultType: Type)(implicit ctx: Context): Type = {
+ def expand(tp: Type) = super.fromParams(params, tp)
+ resultType match {
+ case rt: TypeAlias =>
+ rt.derivedTypeAlias(expand(rt.alias))
+ case rt @ TypeBounds(lo, hi) =>
+ rt.derivedTypeBounds(
+ if (lo.isRef(defn.NothingClass)) lo else expand(lo), expand(hi))
+ case rt =>
+ expand(rt)
+ }
+ }
}
- object PolyType {
- def apply(paramNames: List[TypeName], variances: List[Int])(
- paramBoundsExp: PolyType => List[TypeBounds],
+ object PolyType extends TypeLambdaCompanion[PolyType] {
+ def apply(paramNames: List[TypeName])(
+ paramInfosExp: PolyType => List[TypeBounds],
resultTypeExp: PolyType => Type)(implicit ctx: Context): PolyType = {
- unique(new PolyType(paramNames, variances)(paramBoundsExp, resultTypeExp))
+ unique(new PolyType(paramNames)(paramInfosExp, resultTypeExp))
}
def unapply(tl: PolyType): Some[(List[LambdaParam], Type)] =
Some((tl.typeParams, tl.resType))
def any(n: Int)(implicit ctx: Context) =
- apply(tpnme.syntheticTypeParamNames(n), List.fill(n)(0))(
+ apply(syntheticParamNames(n))(
pt => List.fill(n)(TypeBounds.empty), pt => defn.AnyType)
}
+ private object DepStatus {
+ type DependencyStatus = Byte
+ final val Unknown: DependencyStatus = 0 // not yet computed
+ final val NoDeps: DependencyStatus = 1 // no dependent parameters found
+ final val FalseDeps: DependencyStatus = 2 // all dependent parameters are prefixes of non-depended alias types
+ final val TrueDeps: DependencyStatus = 3 // some truly dependent parameters exist
+ final val StatusMask: DependencyStatus = 3 // the bits indicating actual dependency status
+ final val Provisional: DependencyStatus = 4 // set if dependency status can still change due to type variable instantiations
+ }
+
// ----- HK types: LambdaParam, HKApply ---------------------
/** The parameter of a type lambda */
- case class LambdaParam(tl: PolyType, n: Int) extends TypeParamInfo {
- def isTypeParam(implicit ctx: Context) = true
- def paramName(implicit ctx: Context): TypeName = tl.paramNames(n)
- def paramBounds(implicit ctx: Context): TypeBounds = tl.paramBounds(n)
- def paramBoundsAsSeenFrom(pre: Type)(implicit ctx: Context): TypeBounds = paramBounds
- def paramBoundsOrCompleter(implicit ctx: Context): Type = paramBounds
- def paramVariance(implicit ctx: Context): Int = tl.variances(n)
- def toArg: Type = PolyParam(tl, n)
- def paramRef(implicit ctx: Context): Type = PolyParam(tl, n)
+ case class LambdaParam(tl: TypeLambda, n: Int) extends ParamInfo {
+ type ThisName = TypeName
+ def isTypeParam(implicit ctx: Context) = tl.paramNames.head.isTypeName
+ def paramName(implicit ctx: Context) = tl.paramNames(n)
+ def paramInfo(implicit ctx: Context) = tl.paramInfos(n)
+ def paramInfoAsSeenFrom(pre: Type)(implicit ctx: Context) = paramInfo
+ def paramInfoOrCompleter(implicit ctx: Context): Type = paramInfo
+ def paramVariance(implicit ctx: Context): Int = tl.paramNames(n).variance
+ def toArg: Type = TypeParamRef(tl, n)
+ def paramRef(implicit ctx: Context): Type = TypeParamRef(tl, n)
}
/** A higher kinded type application `C[T_1, ..., T_n]` */
@@ -2715,7 +2845,7 @@ object Types {
override def superType(implicit ctx: Context): Type = {
if (ctx.period != validSuper) {
cachedSuper = tycon match {
- case tp: PolyType => defn.AnyType
+ case tp: HKTypeLambda => defn.AnyType
case tp: TypeVar if !tp.inst.exists =>
// supertype not stable, since underlying might change
return tp.underlying.applyIfParameterized(args)
@@ -2739,9 +2869,9 @@ object Types {
NoType
}
- def typeParams(implicit ctx: Context): List[TypeParamInfo] = {
+ def typeParams(implicit ctx: Context): List[ParamInfo] = {
val tparams = tycon.typeParams
- if (tparams.isEmpty) PolyType.any(args.length).typeParams else tparams
+ if (tparams.isEmpty) HKTypeLambda.any(args.length).typeParams else tparams
}
def derivedAppliedType(tycon: Type, args: List[Type])(implicit ctx: Context): Type =
@@ -2753,8 +2883,8 @@ object Types {
protected def checkInst(implicit ctx: Context): this.type = {
def check(tycon: Type): Unit = tycon.stripTypeVar match {
case tycon: TypeRef if !tycon.symbol.isClass =>
- case _: PolyParam | _: ErrorType | _: WildcardType =>
- case _: PolyType =>
+ case _: TypeParamRef | _: ErrorType | _: WildcardType =>
+ case _: TypeLambda =>
assert(args.exists(_.isInstanceOf[TypeBounds]), s"unreduced type apply: $this")
case tycon: AnnotatedType =>
check(tycon.underlying)
@@ -2773,92 +2903,61 @@ object Types {
unique(new CachedHKApply(tycon, args)).checkInst
}
- // ----- Bound types: MethodParam, PolyParam --------------------------
+ // ----- BoundTypes: ParamRef, RecThis ----------------------------------------
abstract class BoundType extends CachedProxyType with ValueType {
type BT <: Type
- def binder: BT
- // Dotty deviation: copyBoundType was copy, but
- // dotty generates copy methods always automatically, and therefore
- // does not accept same-named method definitions in subclasses.
- // Scala2x, on the other hand, requires them (not sure why!)
+ val binder: BT
def copyBoundType(bt: BT): Type
}
- abstract class ParamType extends BoundType {
+ abstract class ParamRef extends BoundType {
+ type BT <: LambdaType
def paramNum: Int
- def paramName: Name
- }
-
- abstract case class MethodParam(binder: MethodType, paramNum: Int) extends ParamType with SingletonType {
- type BT = MethodType
-
- def paramName = binder.paramNames(paramNum)
+ def paramName: binder.ThisName = binder.paramNames(paramNum)
- override def underlying(implicit ctx: Context): Type = binder.paramTypes(paramNum)
- def copyBoundType(bt: BT) = new MethodParamImpl(bt, paramNum)
+ override def underlying(implicit ctx: Context): Type = {
+ val infos = binder.paramInfos
+ if (infos == null) NoType // this can happen if the referenced generic type is not initialized yet
+ else infos(paramNum)
+ }
- // need to customize hashCode and equals to prevent infinite recursion for dep meth types.
- override def computeHash = addDelta(binder.identityHash, paramNum)
+ override def computeHash = doHash(paramNum, binder.identityHash)
override def equals(that: Any) = that match {
- case that: MethodParam =>
+ case that: ParamRef =>
(this.binder eq that.binder) && this.paramNum == that.paramNum
case _ =>
false
}
- override def toString = s"MethodParam($paramName)"
+ override def toString =
+ try s"ParamRef($paramName)"
+ catch {
+ case ex: IndexOutOfBoundsException => s"ParamRef(<bad index: $paramNum>)"
+ }
}
- class MethodParamImpl(binder: MethodType, paramNum: Int) extends MethodParam(binder, paramNum)
-
- object MethodParam {
- def apply(binder: MethodType, paramNum: Int)(implicit ctx: Context): MethodParam = {
- assertUnerased()
- new MethodParamImpl(binder, paramNum)
- }
+ case class TermParamRef(binder: TermLambda, paramNum: Int) extends ParamRef {
+ type BT = TermLambda
+ def copyBoundType(bt: BT) = TermParamRef(bt, paramNum)
}
- /** TODO Some docs would be nice here! */
- case class PolyParam(binder: PolyType, paramNum: Int) extends ParamType {
- type BT = PolyType
- def copyBoundType(bt: BT) = PolyParam(bt, paramNum)
+ case class TypeParamRef(binder: TypeLambda, paramNum: Int) extends ParamRef {
+ type BT = TypeLambda
+ def copyBoundType(bt: BT) = TypeParamRef(bt, paramNum)
/** Looking only at the structure of `bound`, is one of the following true?
* - fromBelow and param <:< bound
* - !fromBelow and param >:> bound
*/
def occursIn(bound: Type, fromBelow: Boolean)(implicit ctx: Context): Boolean = bound.stripTypeVar match {
- case bound: PolyParam => bound == this
+ case bound: ParamRef => bound == this
case bound: AndOrType =>
def occ1 = occursIn(bound.tp1, fromBelow)
def occ2 = occursIn(bound.tp2, fromBelow)
if (fromBelow == bound.isAnd) occ1 && occ2 else occ1 || occ2
case _ => false
}
-
- def paramName = binder.paramNames(paramNum)
-
- override def underlying(implicit ctx: Context): Type = {
- val bounds = binder.paramBounds
- if (bounds == null) NoType // this can happen if the referenced generic type is not initialized yet
- else bounds(paramNum)
- }
- // no customized hashCode/equals needed because cycle is broken in PolyType
- override def toString =
- try s"PolyParam($paramName)"
- catch {
- case ex: IndexOutOfBoundsException => s"PolyParam(<bad index: $paramNum>)"
- }
-
- override def computeHash = doHash(paramNum, binder.identityHash)
-
- override def equals(that: Any) = that match {
- case that: PolyParam =>
- (this.binder eq that.binder) && this.paramNum == that.paramNum
- case _ =>
- false
- }
}
/** a self-reference to an enclosing recursive type. */
@@ -2929,7 +3028,7 @@ object Types {
* `owningTree` and `owner` are used to determine whether a type-variable can be instantiated
* at some given point. See `Inferencing#interpolateUndetVars`.
*/
- final class TypeVar(val origin: PolyParam, creatorState: TyperState, val bindingTree: untpd.Tree, val owner: Symbol) extends CachedProxyType with ValueType {
+ final class TypeVar(val origin: TypeParamRef, creatorState: TyperState, val bindingTree: untpd.Tree, val owner: Symbol) extends CachedProxyType with ValueType {
/** The permanent instance type of the variable, or NoType is none is given yet */
private[core] var inst: Type = NoType
@@ -3341,9 +3440,8 @@ object Types {
object SAMType {
def zeroParamClass(tp: Type)(implicit ctx: Context): Type = tp match {
case tp: ClassInfo =>
- def zeroParams(tp: Type): Boolean = tp match {
- case pt: PolyType => zeroParams(pt.resultType)
- case mt: MethodType => mt.paramTypes.isEmpty && !mt.resultType.isInstanceOf[MethodType]
+ def zeroParams(tp: Type): Boolean = tp.stripPoly match {
+ case mt: MethodType => mt.paramInfos.isEmpty && !mt.resultType.isInstanceOf[MethodType]
case et: ExprType => true
case _ => false
}
@@ -3426,12 +3524,11 @@ object Types {
tp.derivedClassInfo(pre)
protected def derivedJavaArrayType(tp: JavaArrayType, elemtp: Type): Type =
tp.derivedJavaArrayType(elemtp)
- protected def derivedMethodType(tp: MethodType, formals: List[Type], restpe: Type): Type =
- tp.derivedMethodType(tp.paramNames, formals, restpe)
protected def derivedExprType(tp: ExprType, restpe: Type): Type =
tp.derivedExprType(restpe)
- protected def derivedPolyType(tp: PolyType, pbounds: List[TypeBounds], restpe: Type): Type =
- tp.derivedPolyType(tp.paramNames, pbounds, restpe)
+ // note: currying needed because Scala2 does not support param-dependencies
+ protected def derivedLambdaType(tp: LambdaType)(formals: List[tp.PInfo], restpe: Type): Type =
+ tp.derivedLambdaType(tp.paramNames, formals, restpe)
/** Map this function over given type */
def mapOver(tp: Type): Type = {
@@ -3461,29 +3558,34 @@ object Types {
variance = -variance
derivedTypeBounds(tp, lo1, this(tp.hi))
- case tp: MethodType =>
- def mapOverMethod = {
- variance = -variance
- val ptypes1 = tp.paramTypes mapConserve this
- variance = -variance
- derivedMethodType(tp, ptypes1, this(tp.resultType))
+ case tp: RecType =>
+ derivedRecType(tp, this(tp.parent))
+
+ case tp: TypeVar =>
+ val inst = tp.instanceOpt
+ if (inst.exists) apply(inst) else tp
+
+ case tp: HKApply =>
+ def mapArg(arg: Type, tparam: ParamInfo): Type = {
+ val saved = variance
+ variance *= tparam.paramVariance
+ try this(arg)
+ finally variance = saved
}
- mapOverMethod
+ derivedAppliedType(tp, this(tp.tycon),
+ tp.args.zipWithConserve(tp.typeParams)(mapArg))
case tp: ExprType =>
derivedExprType(tp, this(tp.resultType))
- case tp: PolyType =>
- def mapOverPoly = {
+ case tp: LambdaType =>
+ def mapOverLambda = {
variance = -variance
- val bounds1 = tp.paramBounds.mapConserve(this).asInstanceOf[List[TypeBounds]]
+ val ptypes1 = tp.paramInfos.mapConserve(this).asInstanceOf[List[tp.PInfo]]
variance = -variance
- derivedPolyType(tp, bounds1, this(tp.resultType))
+ derivedLambdaType(tp)(ptypes1, this(tp.resultType))
}
- mapOverPoly
-
- case tp: RecType =>
- derivedRecType(tp, this(tp.parent))
+ mapOverLambda
case tp @ SuperType(thistp, supertp) =>
derivedSuperType(tp, this(thistp), this(supertp))
@@ -3494,21 +3596,7 @@ object Types {
case tp: ClassInfo =>
mapClassInfo(tp)
- case tp: TypeVar =>
- val inst = tp.instanceOpt
- if (inst.exists) apply(inst) else tp
-
- case tp: HKApply =>
- def mapArg(arg: Type, tparam: TypeParamInfo): Type = {
- val saved = variance
- variance *= tparam.paramVariance
- try this(arg)
- finally variance = saved
- }
- derivedAppliedType(tp, this(tp.tycon),
- tp.args.zipWithConserve(tp.typeParams)(mapArg))
-
- case tp: AndOrType =>
+ case tp: AndOrType =>
derivedAndOrType(tp, this(tp.tp1), this(tp.tp2))
case tp: SkolemType =>
@@ -3689,23 +3777,14 @@ object Types {
this(y, hi)
}
- case tp: MethodType =>
- variance = -variance
- val y = foldOver(x, tp.paramTypes)
- variance = -variance
- this(y, tp.resultType)
+ case tp: RecType =>
+ this(x, tp.parent)
case ExprType(restpe) =>
this(x, restpe)
- case tp: PolyType =>
- variance = -variance
- val y = foldOver(x, tp.paramBounds)
- variance = -variance
- this(y, tp.resultType)
-
- case tp: RecType =>
- this(x, tp.parent)
+ case tp: TypeVar =>
+ this(x, tp.underlying)
case SuperType(thistp, supertp) =>
this(this(x, thistp), supertp)
@@ -3714,7 +3793,7 @@ object Types {
this(x, prefix)
case tp @ HKApply(tycon, args) =>
- @tailrec def foldArgs(x: T, tparams: List[TypeParamInfo], args: List[Type]): T =
+ @tailrec def foldArgs(x: T, tparams: List[ParamInfo], args: List[Type]): T =
if (args.isEmpty) {
assert(tparams.isEmpty)
x
@@ -3730,6 +3809,12 @@ object Types {
}
foldArgs(this(x, tycon), tp.typeParams, args)
+ case tp: LambdaType =>
+ variance = -variance
+ val y = foldOver(x, tp.paramInfos)
+ variance = -variance
+ this(y, tp.resultType)
+
case tp: AndOrType =>
this(this(x, tp.tp1), tp.tp2)
@@ -3739,9 +3824,6 @@ object Types {
case AnnotatedType(underlying, annot) =>
this(applyToAnnot(x, annot), underlying)
- case tp: TypeVar =>
- this(x, tp.underlying)
-
case tp: WildcardType =>
this(x, tp.optBounds)
@@ -3804,9 +3886,7 @@ object Types {
apply(x, tp.tref)
case tp: ConstantType =>
apply(x, tp.underlying)
- case tp: MethodParam =>
- apply(x, tp.underlying)
- case tp: PolyParam =>
+ case tp: ParamRef =>
apply(x, tp.underlying)
case _ =>
foldOver(x, tp)
diff --git a/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala
index e0b233ce8..da875c906 100644
--- a/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala
+++ b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala
@@ -199,7 +199,7 @@ class ClassfileParser(
def stripOuterParamFromConstructor() = innerClasses.get(currentClassName) match {
case Some(entry) if !isStatic(entry.jflags) =>
val mt @ MethodTpe(paramNames, paramTypes, resultType) = denot.info
- denot.info = mt.derivedMethodType(paramNames.tail, paramTypes.tail, resultType)
+ denot.info = mt.derivedLambdaType(paramNames.tail, paramTypes.tail, resultType)
case _ =>
}
@@ -209,7 +209,7 @@ class ClassfileParser(
def normalizeConstructorInfo() = {
val mt @ MethodType(paramNames) = denot.info
val rt = classRoot.typeRef appliedTo (classRoot.typeParams map (_.typeRef))
- denot.info = mt.derivedMethodType(paramNames, mt.paramTypes, rt)
+ denot.info = mt.derivedLambdaType(paramNames, mt.paramInfos, rt)
addConstructorTypeParams(denot)
}
@@ -975,7 +975,7 @@ class ClassfileParser(
if (name == nme.CONSTRUCTOR)
tpe match {
case tp: MethodType =>
- tp.derivedMethodType(tp.paramNames, tp.paramTypes, ownerTpe)
+ tp.derivedLambdaType(tp.paramNames, tp.paramInfos, ownerTpe)
}
p = (name, tpe)
values(index) = p
diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala b/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala
index cb1b56c3c..8b2255e94 100644
--- a/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala
+++ b/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala
@@ -151,8 +151,9 @@ Standard-Section: "ASTs" TopLevelStat*
BIND Length boundName_NameRef bounds_Type
// for type-variables defined in a type pattern
BYNAMEtype underlying_Type
- POLYtype Length result_Type NamesTypes // variance encoded in front of name: +/-/=
+ POLYtype Length result_Type NamesTypes
METHODtype Length result_Type NamesTypes // needed for refinements
+ TYPELAMBDAtype Length result_Type NamesTypes // variance encoded in front of name: +/-/(nothing)
PARAMtype Length binder_ASTref paramNum_Nat // needed for refinements
SHARED type_ASTRef
NamesTypes = NameType*
@@ -345,9 +346,10 @@ object TastyFormat {
final val ORtpt = 169
final val METHODtype = 170
final val POLYtype = 171
- final val POLYtpt = 172
- final val PARAMtype = 173
- final val ANNOTATION = 174
+ final val TYPELAMBDAtype = 172
+ final val LAMBDAtpt = 173
+ final val PARAMtype = 174
+ final val ANNOTATION = 175
final val firstSimpleTreeTag = UNITconst
final val firstNatTreeTag = SHARED
@@ -397,7 +399,7 @@ object TastyFormat {
| SINGLETONtpt
| REFINEDtpt
| APPLIEDtpt
- | POLYtpt
+ | LAMBDAtpt
| TYPEBOUNDStpt
| ANNOTATEDtpt
| ANDtpt
@@ -528,8 +530,9 @@ object TastyFormat {
case BYNAMEtype => "BYNAMEtype"
case BYNAMEtpt => "BYNAMEtpt"
case POLYtype => "POLYtype"
- case POLYtpt => "POLYtpt"
case METHODtype => "METHODtype"
+ case TYPELAMBDAtype => "TYPELAMBDAtype"
+ case LAMBDAtpt => "LAMBDAtpt"
case PARAMtype => "PARAMtype"
case ANNOTATION => "ANNOTATION"
case PRIVATEqualified => "PRIVATEqualified"
@@ -543,11 +546,7 @@ object TastyFormat {
case VALDEF | DEFDEF | TYPEDEF | TYPEPARAM | PARAM | NAMEDARG | RETURN | BIND |
SELFDEF | REFINEDtype => 1
case RENAMED | PARAMtype => 2
- case POLYtype | METHODtype => -1
+ case POLYtype | METHODtype | TYPELAMBDAtype => -1
case _ => 0
}
-
- /** Map between variances and name prefixes */
- val varianceToPrefix = Map(-1 -> '-', 0 -> '=', 1 -> '+')
- val prefixToVariance = Map('-' -> -1, '=' -> 0, '+' -> 1)
}
diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala b/compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala
index fb37c9e7d..ce3722ff1 100644
--- a/compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala
+++ b/compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala
@@ -77,7 +77,7 @@ class TastyPrinter(bytes: Array[Byte])(implicit ctx: Context) {
printName(); printTree(); printTrees()
case RETURN =>
printNat(); printTrees()
- case METHODtype | POLYtype =>
+ case METHODtype | POLYtype | TYPELAMBDAtype =>
printTree()
until(end) { printName(); printTree() }
case PARAMtype =>
diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeBuffer.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeBuffer.scala
index 6c7982d78..86e5be2e2 100644
--- a/compiler/src/dotty/tools/dotc/core/tasty/TreeBuffer.scala
+++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeBuffer.scala
@@ -159,7 +159,6 @@ class TreeBuffer extends TastyBuffer(50000) {
val tree = it.next
treeAddrs.get(tree) match {
case addr: Addr => treeAddrs.put(tree, adjusted(addr))
- case addrs: List[Addr] => treeAddrs.put(tree, addrs.map(adjusted))
}
}
}
diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala
index 80270aa25..902d01c21 100644
--- a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala
+++ b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala
@@ -253,23 +253,21 @@ class TreePickler(pickler: TastyPickler) {
case tpe: ExprType =>
writeByte(BYNAMEtype)
pickleType(tpe.underlying)
- case tpe: PolyType =>
- writeByte(POLYtype)
- val paramNames = tpe.typeParams.map(tparam =>
- varianceToPrefix(tparam.paramVariance) +: tparam.paramName)
- pickleMethodic(tpe.resultType, paramNames, tpe.paramBounds)
+ case tpe: HKTypeLambda =>
+ pickleMethodic(TYPELAMBDAtype, tpe)
+ case tpe: PolyType if richTypes =>
+ pickleMethodic(POLYtype, tpe)
case tpe: MethodType if richTypes =>
- writeByte(METHODtype)
- pickleMethodic(tpe.resultType, tpe.paramNames, tpe.paramTypes)
- case tpe: PolyParam =>
- if (!pickleParamType(tpe))
+ pickleMethodic(METHODtype, tpe)
+ case tpe: TypeParamRef =>
+ if (!pickleParamRef(tpe))
// TODO figure out why this case arises in e.g. pickling AbstractFileReader.
ctx.typerState.constraint.entry(tpe) match {
case TypeBounds(lo, hi) if lo eq hi => pickleNewType(lo, richTypes)
case _ => assert(false, s"orphan poly parameter: $tpe")
}
- case tpe: MethodParam =>
- assert(pickleParamType(tpe), s"orphan method parameter: $tpe")
+ case tpe: TermParamRef =>
+ assert(pickleParamRef(tpe), s"orphan method parameter: $tpe")
case tpe: LazyRef =>
pickleType(tpe.ref)
}} catch {
@@ -283,15 +281,17 @@ class TreePickler(pickler: TastyPickler) {
pickleName(qualifiedName(pkg))
}
- def pickleMethodic(result: Type, names: List[Name], types: List[Type])(implicit ctx: Context) =
+ def pickleMethodic(tag: Int, tpe: LambdaType)(implicit ctx: Context) = {
+ writeByte(tag)
withLength {
- pickleType(result, richTypes = true)
- (names, types).zipped.foreach { (name, tpe) =>
+ pickleType(tpe.resultType, richTypes = true)
+ (tpe.paramNames, tpe.paramInfos).zipped.foreach { (name, tpe) =>
pickleName(name); pickleType(tpe)
}
}
+ }
- def pickleParamType(tpe: ParamType)(implicit ctx: Context): Boolean = {
+ def pickleParamRef(tpe: ParamRef)(implicit ctx: Context): Boolean = {
val binder = pickledTypes.get(tpe.binder)
val pickled = binder != null
if (pickled) {
@@ -555,8 +555,8 @@ class TreePickler(pickler: TastyPickler) {
case Annotated(tree, annot) =>
writeByte(ANNOTATEDtpt)
withLength { pickleTree(tree); pickleTree(annot.tree) }
- case PolyTypeTree(tparams, body) =>
- writeByte(POLYtpt)
+ case LambdaTypeTree(tparams, body) =>
+ writeByte(LAMBDAtpt)
withLength { pickleParams(tparams); pickleTree(body) }
case TypeBoundsTree(lo, hi) =>
writeByte(TYPEBOUNDStpt)
diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
index 0e05fb348..a186d1ce4 100644
--- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
+++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
@@ -38,7 +38,7 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, posUnpickle
/** A map from addresses of type entries to the types they define.
* Currently only populated for types that might be recursively referenced
- * from within themselves (i.e. RefinedTypes, PolyTypes, MethodTypes).
+ * from within themselves (i.e. RecTypes, LambdaTypes).
*/
private val typeAtAddr = new mutable.HashMap[Addr, Type]
@@ -227,11 +227,17 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, posUnpickle
def readLengthType(): Type = {
val end = readEnd()
- def readNamesSkipParams: (List[Name], TreeReader) = {
+ def readMethodic[N <: Name, PInfo <: Type, LT <: LambdaType]
+ (companion: LambdaTypeCompanion[N, PInfo, LT], nameMap: Name => N): LT = {
val nameReader = fork
nameReader.skipTree() // skip result
val paramReader = nameReader.fork
- (nameReader.readParamNames(end), paramReader)
+ val paramNames = nameReader.readParamNames(end).map(nameMap)
+ val result = companion(paramNames)(
+ pt => registeringType(pt, paramReader.readParamTypes[PInfo](end)),
+ pt => readType())
+ goto(end)
+ result
}
val result =
@@ -268,25 +274,14 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, posUnpickle
registerSym(start, sym)
TypeRef.withFixedSym(NoPrefix, sym.name, sym)
case POLYtype =>
- val (rawNames, paramReader) = readNamesSkipParams
- val (variances, paramNames) = rawNames
- .map(name => (prefixToVariance(name.head), name.tail.toTypeName)).unzip
- val result = PolyType(paramNames, variances)(
- pt => registeringType(pt, paramReader.readParamTypes[TypeBounds](end)),
- pt => readType())
- goto(end)
- result
+ readMethodic(PolyType, _.toTypeName)
case METHODtype =>
- val (names, paramReader) = readNamesSkipParams
- val result = MethodType(names.map(_.toTermName))(
- mt => registeringType(mt, paramReader.readParamTypes[Type](end)),
- mt => readType())
- goto(end)
- result
+ readMethodic(MethodType, _.toTermName)
+ case TYPELAMBDAtype =>
+ readMethodic(HKTypeLambda, _.toTypeName)
case PARAMtype =>
readTypeRef() match {
- case binder: PolyType => PolyParam(binder, readNat())
- case binder: MethodType => MethodParam(binder, readNat())
+ case binder: LambdaType => binder.newParamRef(readNat())
}
case CLASSconst =>
ConstantType(Constant(readType()))
@@ -412,7 +407,7 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, posUnpickle
}
def isAbstractType(ttag: Int)(implicit ctx: Context): Boolean = nextUnsharedTag match {
- case POLYtpt =>
+ case LAMBDAtpt =>
val rdr = fork
rdr.reader.readByte() // tag
rdr.reader.readNat() // length
@@ -736,7 +731,9 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, posUnpickle
// no longer necessary.
goto(end)
setPos(start, tree)
- sym.info = ta.avoidPrivateLeaks(sym, tree.pos)
+ if (!sym.isType) { // Only terms might have leaky aliases, see the documentation of `checkNoPrivateLeaks`
+ sym.info = ta.avoidPrivateLeaks(sym, tree.pos)
+ }
tree
}
@@ -1033,11 +1030,11 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, posUnpickle
OrTypeTree(readTpt(), readTpt())
case ANNOTATEDtpt =>
Annotated(readTpt(), readTerm())
- case POLYtpt =>
+ case LAMBDAtpt =>
val localCtx = localNonClassCtx
val tparams = readParams[TypeDef](TYPEPARAM)(localCtx)
val body = readTpt()(localCtx)
- PolyTypeTree(tparams, body)
+ LambdaTypeTree(tparams, body)
case TYPEBOUNDStpt =>
TypeBoundsTree(readTpt(), readTpt())
case _ =>
diff --git a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala
index 688a2d007..cf99bb022 100644
--- a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala
+++ b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala
@@ -42,13 +42,15 @@ object Scala2Unpickler {
/** Convert temp poly type to poly type and leave other types alone. */
def translateTempPoly(tp: Type)(implicit ctx: Context): Type = tp match {
- case TempPolyType(tparams, restpe) => restpe.LambdaAbstract(tparams)
+ case TempPolyType(tparams, restpe) =>
+ (if (tparams.head.owner.isTerm) PolyType else HKTypeLambda)
+ .fromParams(tparams, restpe)
case tp => tp
}
def addConstructorTypeParams(denot: SymDenotation)(implicit ctx: Context) = {
assert(denot.isConstructor)
- denot.info = denot.info.LambdaAbstract(denot.owner.typeParams)
+ denot.info = PolyType.fromParams(denot.owner.typeParams, denot.info)
}
/** Convert array parameters denoting a repeated parameter of a Java method
@@ -56,7 +58,7 @@ object Scala2Unpickler {
*/
def arrayToRepeated(tp: Type)(implicit ctx: Context): Type = tp match {
case tp: MethodType =>
- val lastArg = tp.paramTypes.last
+ val lastArg = tp.paramInfos.last
assert(lastArg isRef defn.ArrayClass)
val elemtp0 :: Nil = lastArg.baseArgInfos(defn.ArrayClass)
val elemtp = elemtp0 match {
@@ -65,12 +67,12 @@ object Scala2Unpickler {
case _ =>
elemtp0
}
- tp.derivedMethodType(
+ tp.derivedLambdaType(
tp.paramNames,
- tp.paramTypes.init :+ defn.RepeatedParamType.appliedTo(elemtp),
+ tp.paramInfos.init :+ defn.RepeatedParamType.appliedTo(elemtp),
tp.resultType)
case tp: PolyType =>
- tp.derivedPolyType(tp.paramNames, tp.paramBounds, arrayToRepeated(tp.resultType))
+ tp.derivedLambdaType(tp.paramNames, tp.paramInfos, arrayToRepeated(tp.resultType))
}
def ensureConstructor(cls: ClassSymbol, scope: Scope)(implicit ctx: Context) =
@@ -745,7 +747,7 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas
TempClassInfoType(until(end, readTypeRef), symScope(clazz), clazz)
case METHODtpe | IMPLICITMETHODtpe =>
val restpe = readTypeRef()
- val params = until(end, readSymbolRef)
+ val params = until(end, readSymbolRef).asInstanceOf[List[TermSymbol]]
def isImplicit =
tag == IMPLICITMETHODtpe ||
params.nonEmpty && (params.head is Implicit)
diff --git a/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala b/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala
index 6b73a9456..47f201a09 100644
--- a/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala
+++ b/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala
@@ -828,11 +828,11 @@ object JavaParsers {
val superclazz = Apply(TypeApply(
Select(New(javaLangDot(tpnme.Enum)), nme.CONSTRUCTOR), List(enumType)),
List(Literal(Constant(null)),Literal(Constant(0))))
- val enum = atPos(start, nameOffset) {
+ val enumclazz = atPos(start, nameOffset) {
TypeDef(name,
makeTemplate(superclazz :: interfaces, body, List(), true)).withMods(mods | Flags.Enum)
}
- addCompanionObject(consts ::: statics ::: predefs, enum)
+ addCompanionObject(consts ::: statics ::: predefs, enumclazz)
}
def enumConst(enumType: Tree) = {
diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala
index b644c94cc..3e3673e5e 100644
--- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala
+++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala
@@ -49,6 +49,13 @@ object Parsers {
val Class, Type, TypeParam, Def = Value
}
+ private implicit class AddDeco(val buf: ListBuffer[Tree]) extends AnyVal {
+ def +++=(x: Tree) = x match {
+ case x: Thicket => buf ++= x.trees
+ case x => buf += x
+ }
+ }
+
/** The parse starting point depends on whether the source file is self-contained:
* if not, the AST will be supplemented.
*/
@@ -721,7 +728,7 @@ object Parsers {
val start = in.offset
val tparams = typeParamClause(ParamOwner.TypeParam)
if (in.token == ARROW)
- atPos(start, in.skipToken())(PolyTypeTree(tparams, typ()))
+ atPos(start, in.skipToken())(LambdaTypeTree(tparams, typ()))
else { accept(ARROW); typ() }
}
else infixType()
@@ -1873,29 +1880,32 @@ object Parsers {
mods1
}
- /** Def ::= val PatDef
- * | var VarDef
- * | def DefDef
- * | type {nl} TypeDcl
- * | TmplDef
- * Dcl ::= val ValDcl
- * | var ValDcl
- * | def DefDcl
- * | type {nl} TypeDcl
+ /** Def ::= val PatDef
+ * | var VarDef
+ * | def DefDef
+ * | type {nl} TypeDcl
+ * | TmplDef
+ * Dcl ::= val ValDcl
+ * | var ValDcl
+ * | def DefDcl
+ * | type {nl} TypeDcl
+ * EnumCase ::= `case' (EnumClassDef | ObjectDef)
*/
def defOrDcl(start: Int, mods: Modifiers): Tree = in.token match {
case VAL =>
val mod = atPos(in.skipToken()) { Mod.Val() }
val mods1 = mods.withAddedMod(mod)
- patDefOrDcl(start, mods1, in.getDocComment(start))
+ patDefOrDcl(start, mods1)
case VAR =>
val mod = atPos(in.skipToken()) { Mod.Var() }
val mod1 = addMod(mods, mod)
- patDefOrDcl(start, mod1, in.getDocComment(start))
+ patDefOrDcl(start, mod1)
case DEF =>
- defDefOrDcl(start, posMods(start, mods), in.getDocComment(start))
+ defDefOrDcl(start, posMods(start, mods))
case TYPE =>
- typeDefOrDcl(start, posMods(start, mods), in.getDocComment(start))
+ typeDefOrDcl(start, posMods(start, mods))
+ case CASE =>
+ enumCase(start, mods)
case _ =>
tmplDef(start, mods)
}
@@ -1905,7 +1915,7 @@ object Parsers {
* ValDcl ::= id {`,' id} `:' Type
* VarDcl ::= id {`,' id} `:' Type
*/
- def patDefOrDcl(start: Offset, mods: Modifiers, docstring: Option[Comment] = None): Tree = atPos(start, nameStart) {
+ def patDefOrDcl(start: Offset, mods: Modifiers): Tree = atPos(start, nameStart) {
val lhs = commaSeparated(pattern2)
val tpt = typedOpt()
val rhs =
@@ -1920,7 +1930,7 @@ object Parsers {
} else EmptyTree
lhs match {
case (id @ Ident(name: TermName)) :: Nil => {
- ValDef(name, tpt, rhs).withMods(mods).setComment(docstring)
+ ValDef(name, tpt, rhs).withMods(mods).setComment(in.getDocComment(start))
} case _ =>
PatDef(mods, lhs, tpt, rhs)
}
@@ -1946,7 +1956,7 @@ object Parsers {
* DefDcl ::= DefSig `:' Type
* DefSig ::= id [DefTypeParamClause] ParamClauses
*/
- def defDefOrDcl(start: Offset, mods: Modifiers, docstring: Option[Comment] = None): Tree = atPos(start, nameStart) {
+ def defDefOrDcl(start: Offset, mods: Modifiers): Tree = atPos(start, nameStart) {
def scala2ProcedureSyntax(resultTypeStr: String) = {
val toInsert =
if (in.token == LBRACE) s"$resultTypeStr ="
@@ -1989,7 +1999,7 @@ object Parsers {
accept(EQUALS)
expr()
}
- DefDef(name, tparams, vparamss, tpt, rhs).withMods(mods1).setComment(docstring)
+ DefDef(name, tparams, vparamss, tpt, rhs).withMods(mods1).setComment(in.getDocComment(start))
}
}
@@ -2023,7 +2033,7 @@ object Parsers {
/** TypeDef ::= type id [TypeParamClause] `=' Type
* TypeDcl ::= type id [TypeParamClause] TypeBounds
*/
- def typeDefOrDcl(start: Offset, mods: Modifiers, docstring: Option[Comment] = None): Tree = {
+ def typeDefOrDcl(start: Offset, mods: Modifiers): Tree = {
newLinesOpt()
atPos(start, nameStart) {
val name = ident().toTypeName
@@ -2031,9 +2041,9 @@ object Parsers {
in.token match {
case EQUALS =>
in.nextToken()
- TypeDef(name, lambdaAbstract(tparams, typ())).withMods(mods).setComment(docstring)
+ TypeDef(name, lambdaAbstract(tparams, typ())).withMods(mods).setComment(in.getDocComment(start))
case SUPERTYPE | SUBTYPE | SEMI | NEWLINE | NEWLINES | COMMA | RBRACE | EOF =>
- TypeDef(name, lambdaAbstract(tparams, typeBounds())).withMods(mods).setComment(docstring)
+ TypeDef(name, lambdaAbstract(tparams, typeBounds())).withMods(mods).setComment(in.getDocComment(start))
case _ =>
syntaxErrorOrIncomplete("`=', `>:', or `<:' expected")
EmptyTree
@@ -2041,43 +2051,51 @@ object Parsers {
}
}
- /** TmplDef ::= ([`case'] `class' | `trait') ClassDef
+ /** TmplDef ::= ([`case' | `enum]'] ‘class’ | trait’) ClassDef
* | [`case'] `object' ObjectDef
+ * | `enum' EnumDef
*/
def tmplDef(start: Int, mods: Modifiers): Tree = {
- val docstring = in.getDocComment(start)
in.token match {
case TRAIT =>
- classDef(start, posMods(start, addFlag(mods, Trait)), docstring)
+ classDef(start, posMods(start, addFlag(mods, Trait)))
case CLASS =>
- classDef(start, posMods(start, mods), docstring)
+ classDef(start, posMods(start, mods))
case CASECLASS =>
- classDef(start, posMods(start, mods | Case), docstring)
+ classDef(start, posMods(start, mods | Case))
case OBJECT =>
- objectDef(start, posMods(start, mods | Module), docstring)
+ objectDef(start, posMods(start, mods | Module))
case CASEOBJECT =>
- objectDef(start, posMods(start, mods | Case | Module), docstring)
+ objectDef(start, posMods(start, mods | Case | Module))
+ case ENUM =>
+ val enumMod = atPos(in.skipToken()) { Mod.Enum() }
+ if (in.token == CLASS) tmplDef(start, addMod(mods, enumMod))
+ else enumDef(start, mods, enumMod)
case _ =>
syntaxErrorOrIncomplete("expected start of definition")
EmptyTree
}
}
- /** ClassDef ::= id [ClsTypeParamClause]
- * [ConstrMods] ClsParamClauses TemplateOpt
+ /** ClassDef ::= id ClassConstr TemplateOpt
*/
- def classDef(start: Offset, mods: Modifiers, docstring: Option[Comment]): TypeDef = atPos(start, nameStart) {
- val name = ident().toTypeName
- val constr = atPos(in.lastOffset) {
- val tparams = typeParamClauseOpt(ParamOwner.Class)
- val cmods = constrModsOpt(name)
- val vparamss = paramClauses(name, mods is Case)
+ def classDef(start: Offset, mods: Modifiers): TypeDef = atPos(start, nameStart) {
+ classDefRest(start, mods, ident().toTypeName)
+ }
- makeConstructor(tparams, vparamss).withMods(cmods)
- }
+ def classDefRest(start: Offset, mods: Modifiers, name: TypeName): TypeDef = {
+ val constr = classConstr(name, isCaseClass = mods is Case)
val templ = templateOpt(constr)
+ TypeDef(name, templ).withMods(mods).setComment(in.getDocComment(start))
+ }
- TypeDef(name, templ).withMods(mods).setComment(docstring)
+ /** ClassConstr ::= [ClsTypeParamClause] [ConstrMods] ClsParamClauses
+ */
+ def classConstr(owner: Name, isCaseClass: Boolean = false): DefDef = atPos(in.lastOffset) {
+ val tparams = typeParamClauseOpt(ParamOwner.Class)
+ val cmods = constrModsOpt(owner)
+ val vparamss = paramClauses(owner, isCaseClass)
+ makeConstructor(tparams, vparamss).withMods(cmods)
}
/** ConstrMods ::= AccessModifier
@@ -2093,11 +2111,73 @@ object Parsers {
/** ObjectDef ::= id TemplateOpt
*/
- def objectDef(start: Offset, mods: Modifiers, docstring: Option[Comment] = None): ModuleDef = atPos(start, nameStart) {
- val name = ident()
+ def objectDef(start: Offset, mods: Modifiers): ModuleDef = atPos(start, nameStart) {
+ objectDefRest(start, mods, ident())
+ }
+
+ def objectDefRest(start: Offset, mods: Modifiers, name: TermName): ModuleDef = {
val template = templateOpt(emptyConstructor)
+ ModuleDef(name, template).withMods(mods).setComment(in.getDocComment(start))
+ }
+
+ /** id ClassConstr [`extends' [ConstrApps]]
+ * [nl] ‘{’ EnumCaseStats ‘}’
+ */
+ def enumDef(start: Offset, mods: Modifiers, enumMod: Mod): Thicket = {
+ val point = nameStart
+ val modName = ident()
+ val clsName = modName.toTypeName
+ val constr = classConstr(clsName)
+ val parents =
+ if (in.token == EXTENDS) {
+ in.nextToken();
+ newLineOptWhenFollowedBy(LBRACE)
+ if (in.token == LBRACE) Nil else tokenSeparated(WITH, constrApp)
+ }
+ else Nil
+ val clsDef = atPos(start, point) {
+ TypeDef(clsName, Template(constr, parents, EmptyValDef, Nil))
+ .withMods(addMod(mods, enumMod)).setComment(in.getDocComment(start))
+ }
+ newLineOptWhenFollowedBy(LBRACE)
+ val modDef = atPos(in.offset) {
+ val body = inBraces(enumCaseStats)
+ ModuleDef(modName, Template(emptyConstructor, Nil, EmptyValDef, body))
+ .withMods(mods)
+ }
+ Thicket(clsDef :: modDef :: Nil)
+ }
+
+ /** EnumCaseStats = EnumCaseStat {semi EnumCaseStat */
+ def enumCaseStats(): List[DefTree] = {
+ val cases = new ListBuffer[DefTree] += enumCaseStat()
+ while (in.token != RBRACE) {
+ acceptStatSep()
+ cases += enumCaseStat()
+ }
+ cases.toList
+ }
+
+ /** EnumCaseStat = {Annotation [nl]} {Modifier} EnumCase */
+ def enumCaseStat(): DefTree =
+ enumCase(in.offset, defAnnotsMods(modifierTokens))
- ModuleDef(name, template).withMods(mods).setComment(docstring)
+ /** EnumCase = `case' (EnumClassDef | ObjectDef) */
+ def enumCase(start: Offset, mods: Modifiers): DefTree = {
+ val mods1 = mods.withAddedMod(atPos(in.offset)(Mod.EnumCase())) | Case
+ accept(CASE)
+ atPos(start, nameStart) {
+ val id = termIdent()
+ if (in.token == LBRACKET || in.token == LPAREN)
+ classDefRest(start, mods1, id.name.toTypeName)
+ else if (in.token == COMMA) {
+ in.nextToken()
+ val ids = commaSeparated(termIdent)
+ PatDef(mods1, id :: ids, TypeTree(), EmptyTree)
+ }
+ else
+ objectDefRest(start, mods1, id.name.asTermName)
+ }
}
/* -------- TEMPLATES ------------------------------------------- */
@@ -2191,7 +2271,7 @@ object Parsers {
else if (in.token == IMPORT)
stats ++= importClause()
else if (in.token == AT || isTemplateIntro || isModifier)
- stats += tmplDef(in.offset, defAnnotsMods(modifierTokens))
+ stats +++= tmplDef(in.offset, defAnnotsMods(modifierTokens))
else if (!isStatSep) {
if (in.token == CASE)
syntaxErrorOrIncomplete("only `case class` or `case object` allowed")
@@ -2209,8 +2289,8 @@ object Parsers {
* TemplateStat ::= Import
* | Annotations Modifiers Def
* | Annotations Modifiers Dcl
+ * | EnumCaseStat
* | Expr1
- * | super ArgumentExprs {ArgumentExprs}
* |
*/
def templateStatSeq(): (ValDef, List[Tree]) = checkNoEscapingPlaceholders {
@@ -2240,8 +2320,8 @@ object Parsers {
stats ++= importClause()
else if (isExprIntro)
stats += expr1()
- else if (isDefIntro(modifierTokens))
- stats += defOrDcl(in.offset, defAnnotsMods(modifierTokens))
+ else if (isDefIntro(modifierTokensOrCase))
+ stats +++= defOrDcl(in.offset, defAnnotsMods(modifierTokens))
else if (!isStatSep) {
exitOnError = mustStartStat
syntaxErrorOrIncomplete("illegal start of definition")
@@ -2299,9 +2379,9 @@ object Parsers {
val start = in.offset
val imods = implicitMods()
if (isBindingIntro) stats += implicitClosure(start, Location.InBlock, imods)
- else stats += localDef(start, imods)
+ else stats +++= localDef(start, imods)
} else {
- stats += localDef(in.offset)
+ stats +++= localDef(in.offset)
}
else if (!isStatSep && (in.token != CASE)) {
exitOnError = mustStartStat
@@ -2323,8 +2403,7 @@ object Parsers {
if (in.token == PACKAGE) {
in.nextToken()
if (in.token == OBJECT) {
- val docstring = in.getDocComment(start)
- ts += objectDef(start, atPos(start, in.skipToken()) { Modifiers(Package) }, docstring)
+ ts += objectDef(start, atPos(start, in.skipToken()) { Modifiers(Package) })
if (in.token != EOF) {
acceptStatSep()
ts ++= topStatSeq()
diff --git a/compiler/src/dotty/tools/dotc/parsing/Scanners.scala b/compiler/src/dotty/tools/dotc/parsing/Scanners.scala
index 847f600c0..ff5019dc9 100644
--- a/compiler/src/dotty/tools/dotc/parsing/Scanners.scala
+++ b/compiler/src/dotty/tools/dotc/parsing/Scanners.scala
@@ -10,6 +10,7 @@ import util.Chars._
import Tokens._
import scala.annotation.{ switch, tailrec }
import scala.collection.mutable
+import scala.collection.immutable.SortedMap
import mutable.ListBuffer
import Utility.isNameStart
import rewrite.Rewrites.patch
@@ -174,37 +175,24 @@ object Scanners {
class Scanner(source: SourceFile, override val startFrom: Offset = 0)(implicit ctx: Context) extends ScannerCommon(source)(ctx) {
val keepComments = ctx.settings.YkeepComments.value
- /** All doc comments as encountered, each list contains doc comments from
- * the same block level. Starting with the deepest level and going upward
- */
- private[this] var docsPerBlockStack: List[List[Comment]] = List(Nil)
-
- /** Adds level of nesting to docstrings */
- def enterBlock(): Unit =
- docsPerBlockStack = List(Nil) ::: docsPerBlockStack
-
- /** Removes level of nesting for docstrings */
- def exitBlock(): Unit = docsPerBlockStack = docsPerBlockStack match {
- case x :: Nil => List(Nil)
- case _ => docsPerBlockStack.tail
+ /** All doc comments kept by their end position in a `Map` */
+ private[this] var docstringMap: SortedMap[Int, Comment] = SortedMap.empty
+
+ private[this] def addComment(comment: Comment): Unit = {
+ val lookahead = lookaheadReader
+ def nextPos: Int = (lookahead.getc(): @switch) match {
+ case ' ' | '\t' => nextPos
+ case CR | LF | FF =>
+ // if we encounter line delimitng whitespace we don't count it, since
+ // it seems not to affect positions in source
+ nextPos - 1
+ case _ => lookahead.charOffset - 1
+ }
+ docstringMap = docstringMap + (nextPos -> comment)
}
/** Returns the closest docstring preceding the position supplied */
- def getDocComment(pos: Int): Option[Comment] = {
- def closest(c: Comment, docstrings: List[Comment]): Comment = docstrings match {
- case x :: xs if (c.pos.end < x.pos.end && x.pos.end <= pos) => closest(x, xs)
- case Nil => c
- }
-
- docsPerBlockStack match {
- case (list @ (x :: xs)) :: _ => {
- val c = closest(x, xs)
- docsPerBlockStack = list.dropWhile(_ != c).tail :: docsPerBlockStack.tail
- Some(c)
- }
- case _ => None
- }
- }
+ def getDocComment(pos: Int): Option[Comment] = docstringMap.get(pos)
/** A buffer for comments */
val commentBuf = new StringBuilder
@@ -294,7 +282,10 @@ object Scanners {
if (!sepRegions.isEmpty && sepRegions.head == lastToken)
sepRegions = sepRegions.tail
case ARROW =>
- if (!sepRegions.isEmpty && sepRegions.head == lastToken)
+ if (!sepRegions.isEmpty && sepRegions.head == ARROW)
+ sepRegions = sepRegions.tail
+ case EXTENDS =>
+ if (!sepRegions.isEmpty && sepRegions.head == ARROW)
sepRegions = sepRegions.tail
case STRINGLIT =>
if (inMultiLineInterpolation)
@@ -330,7 +321,8 @@ object Scanners {
if (isAfterLineEnd() &&
(canEndStatTokens contains lastToken) &&
(canStartStatTokens contains token) &&
- (sepRegions.isEmpty || sepRegions.head == RBRACE)) {
+ (sepRegions.isEmpty || sepRegions.head == RBRACE ||
+ sepRegions.head == ARROW && token == CASE)) {
next copyFrom this
// todo: make offset line-end of previous line?
offset = if (lineStartOffset <= offset) lineStartOffset else lastLineStartOffset
@@ -535,13 +527,13 @@ object Scanners {
case ',' =>
nextChar(); token = COMMA
case '(' =>
- enterBlock(); nextChar(); token = LPAREN
+ nextChar(); token = LPAREN
case '{' =>
- enterBlock(); nextChar(); token = LBRACE
+ nextChar(); token = LBRACE
case ')' =>
- exitBlock(); nextChar(); token = RPAREN
+ nextChar(); token = RPAREN
case '}' =>
- exitBlock(); nextChar(); token = RBRACE
+ nextChar(); token = RBRACE
case '[' =>
nextChar(); token = LBRACKET
case ']' =>
@@ -606,11 +598,12 @@ object Scanners {
val start = lastCharOffset
def finishComment(): Boolean = {
if (keepComments) {
- val pos = Position(start, charOffset, start)
+ val pos = Position(start, charOffset - 1, start)
val comment = Comment(pos, flushBuf(commentBuf))
- if (comment.isDocComment)
- docsPerBlockStack = (docsPerBlockStack.head :+ comment) :: docsPerBlockStack.tail
+ if (comment.isDocComment) {
+ addComment(comment)
+ }
}
true
diff --git a/compiler/src/dotty/tools/dotc/parsing/Tokens.scala b/compiler/src/dotty/tools/dotc/parsing/Tokens.scala
index 8d42e525a..d2ea9240c 100644
--- a/compiler/src/dotty/tools/dotc/parsing/Tokens.scala
+++ b/compiler/src/dotty/tools/dotc/parsing/Tokens.scala
@@ -92,6 +92,7 @@ abstract class TokensCommon {
//final val THEN = 60; enter(THEN, "then")
//final val FORSOME = 61; enter(FORSOME, "forSome") // TODO: deprecate
//final val INLINE = 62; enter(INLINE, "inline")
+ //final val ENUM = 63; enter(ENUM, "enum")
/** special symbols */
final val COMMA = 70; enter(COMMA, "','")
@@ -175,6 +176,7 @@ object Tokens extends TokensCommon {
final val THEN = 60; enter(THEN, "then")
final val FORSOME = 61; enter(FORSOME, "forSome") // TODO: deprecate
final val INLINE = 62; enter(INLINE, "inline")
+ final val ENUM = 63; enter(ENUM, "enum")
/** special symbols */
final val NEWLINE = 78; enter(NEWLINE, "end of statement", "new line")
@@ -192,7 +194,7 @@ object Tokens extends TokensCommon {
/** XML mode */
final val XMLSTART = 96; enter(XMLSTART, "$XMLSTART$<") // TODO: deprecate
- final val alphaKeywords = tokenRange(IF, INLINE)
+ final val alphaKeywords = tokenRange(IF, ENUM)
final val symbolicKeywords = tokenRange(USCORE, VIEWBOUND)
final val symbolicTokens = tokenRange(COMMA, VIEWBOUND)
final val keywords = alphaKeywords | symbolicKeywords
@@ -213,7 +215,7 @@ object Tokens extends TokensCommon {
final val canStartBindingTokens = identifierTokens | BitSet(USCORE, LPAREN)
- final val templateIntroTokens = BitSet(CLASS, TRAIT, OBJECT, CASECLASS, CASEOBJECT)
+ final val templateIntroTokens = BitSet(CLASS, TRAIT, OBJECT, ENUM, CASECLASS, CASEOBJECT)
final val dclIntroTokens = BitSet(DEF, VAL, VAR, TYPE)
@@ -228,6 +230,8 @@ object Tokens extends TokensCommon {
final val modifierTokens = localModifierTokens | accessModifierTokens | BitSet(
OVERRIDE)
+ final val modifierTokensOrCase = modifierTokens | BitSet(CASE)
+
/** Is token only legal as start of statement (eof also included)? */
final val mustStartStatTokens = defIntroTokens | modifierTokens | BitSet(
IMPORT, PACKAGE)
diff --git a/compiler/src/dotty/tools/dotc/printing/Formatting.scala b/compiler/src/dotty/tools/dotc/printing/Formatting.scala
index 05f1af9d7..e8fa45403 100644
--- a/compiler/src/dotty/tools/dotc/printing/Formatting.scala
+++ b/compiler/src/dotty/tools/dotc/printing/Formatting.scala
@@ -107,7 +107,7 @@ object Formatting {
else nonSensicalStartTag + str + nonSensicalEndTag
}
- private type Recorded = AnyRef /*Symbol | PolyParam*/
+ private type Recorded = AnyRef /*Symbol | TypeParamRef*/
private class Seen extends mutable.HashMap[String, List[Recorded]] {
@@ -135,8 +135,8 @@ object Formatting {
if ((sym is ModuleClass) && sym.sourceModule.exists) simpleNameString(sym.sourceModule)
else seen.record(super.simpleNameString(sym), sym)
- override def polyParamNameString(param: PolyParam): String =
- seen.record(super.polyParamNameString(param), param)
+ override def TypeParamRefNameString(param: TypeParamRef): String =
+ seen.record(super.TypeParamRefNameString(param), param)
}
/** Create explanation for single `Recorded` type or symbol */
@@ -161,7 +161,7 @@ object Formatting {
}
entry match {
- case param: PolyParam =>
+ case param: TypeParamRef =>
s"is a type variable${addendum("constraint", ctx.typeComparer.bounds(param))}"
case sym: Symbol =>
s"is a ${ctx.printer.kindString(sym)}${sym.showExtendedLocation}${addendum("bounds", sym.info)}"
@@ -175,7 +175,7 @@ object Formatting {
*/
private def explanations(seen: Seen)(implicit ctx: Context): String = {
def needsExplanation(entry: Recorded) = entry match {
- case param: PolyParam => ctx.typerState.constraint.contains(param)
+ case param: TypeParamRef => ctx.typerState.constraint.contains(param)
case _ => false
}
@@ -213,9 +213,11 @@ object Formatting {
* ex"disambiguate $tpe1 and $tpe2"
* ```
*/
- def explained2(op: Context => String)(implicit ctx: Context): String = {
+ def explained(op: Context => String)(implicit ctx: Context): String = {
val seen = new Seen
- op(explainCtx(seen)) ++ explanations(seen)
+ val msg = op(explainCtx(seen))
+ val addendum = explanations(seen)
+ if (addendum.isEmpty) msg else msg ++ "\n\n" ++ addendum
}
/** When getting a type mismatch it is useful to disambiguate placeholders like:
diff --git a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala
index 67d44daa1..d5014b547 100644
--- a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala
+++ b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala
@@ -170,21 +170,20 @@ class PlainPrinter(_ctx: Context) extends Printer {
def paramText(name: TermName, tp: Type) = toText(name) ~ ": " ~ toText(tp)
changePrec(GlobalPrec) {
(if (tp.isImplicit) "(implicit " else "(") ~
- Text((tp.paramNames, tp.paramTypes).zipped map paramText, ", ") ~
+ Text((tp.paramNames, tp.paramInfos).zipped map paramText, ", ") ~
")" ~ toText(tp.resultType)
}
case tp: ExprType =>
changePrec(GlobalPrec) { "=> " ~ toText(tp.resultType) }
- case tp: PolyType =>
- def paramText(variance: Int, name: Name, bounds: TypeBounds): Text =
- varianceString(variance) ~ name.toString ~ toText(bounds)
+ case tp: TypeLambda =>
+ def paramText(name: Name, bounds: TypeBounds): Text = name.toString ~ toText(bounds)
changePrec(GlobalPrec) {
- "[" ~ Text((tp.variances, tp.paramNames, tp.paramBounds).zipped.map(paramText), ", ") ~
+ "[" ~ Text((tp.paramNames, tp.paramInfos).zipped.map(paramText), ", ") ~
"]" ~ (" => " provided !tp.resultType.isInstanceOf[MethodType]) ~
toTextGlobal(tp.resultType)
}
- case tp: PolyParam =>
- polyParamNameString(tp) ~ polyHash(tp.binder)
+ case tp: TypeParamRef =>
+ TypeParamRefNameString(tp) ~ lambdaHash(tp.binder)
case AnnotatedType(tpe, annot) =>
toTextLocal(tpe) ~ " " ~ toText(annot)
case HKApply(tycon, args) =>
@@ -207,17 +206,18 @@ class PlainPrinter(_ctx: Context) extends Printer {
}
}.close
- protected def polyParamNameString(name: TypeName): String = name.toString
+ protected def TypeParamRefNameString(name: TypeName): String = name.toString
- protected def polyParamNameString(param: PolyParam): String = polyParamNameString(param.binder.paramNames(param.paramNum))
+ protected def TypeParamRefNameString(param: TypeParamRef): String =
+ TypeParamRefNameString(param.binder.paramNames(param.paramNum))
/** The name of the symbol without a unique id. Under refined printing,
* the decoded original name.
*/
protected def simpleNameString(sym: Symbol): String = nameString(sym.name)
- /** If -uniqid is set, the hashcode of the polytype, after a # */
- protected def polyHash(pt: PolyType): Text =
+ /** If -uniqid is set, the hashcode of the lambda type, after a # */
+ protected def lambdaHash(pt: LambdaType): Text =
if (ctx.settings.uniqid.value) "#" + pt.hashCode else ""
/** If -uniqid is set, the unique id of symbol, after a # */
@@ -259,8 +259,8 @@ class PlainPrinter(_ctx: Context) extends Printer {
"Super(" ~ toTextGlobal(thistpe) ~ ")"
case tp @ ConstantType(value) =>
toText(value)
- case MethodParam(mt, idx) =>
- nameString(mt.paramNames(idx))
+ case pref: TermParamRef =>
+ nameString(pref.binder.paramNames(pref.paramNum))
case tp: RecThis =>
val idx = openRecs.reverse.indexOf(tp.binder)
if (idx >= 0) selfRecName(idx + 1)
diff --git a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala
index 8a33472b8..76bce7920 100644
--- a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala
+++ b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala
@@ -401,7 +401,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
toTextLocal(tpt) ~ " " ~ blockText(refines)
case AppliedTypeTree(tpt, args) =>
toTextLocal(tpt) ~ "[" ~ Text(args map argText, ", ") ~ "]"
- case PolyTypeTree(tparams, body) =>
+ case LambdaTypeTree(tparams, body) =>
changePrec(GlobalPrec) {
tparamsText(tparams) ~ " -> " ~ toText(body)
}
@@ -451,7 +451,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
(if (tree.hasType && ctx.settings.verbose.value) i"[decls = ${tree.symbol.info.decls}]" else "")
case rhs: TypeBoundsTree =>
typeDefText(tparamsTxt, toText(rhs))
- case PolyTypeTree(tparams, body) =>
+ case LambdaTypeTree(tparams, body) =>
recur(body, tparamsText(tparams))
case rhs =>
typeDefText(tparamsTxt, optText(rhs)(" = " ~ _))
@@ -604,7 +604,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
def optText[T >: Untyped](tree: List[Tree[T]])(encl: Text => Text): Text =
if (tree.exists(!_.isEmpty)) encl(blockText(tree)) else ""
- override protected def polyParamNameString(name: TypeName): String =
+ override protected def TypeParamRefNameString(name: TypeName): String =
name.unexpandedName.toString
override protected def treatAsTypeParam(sym: Symbol): Boolean = sym is TypeParam
diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala
index 57365658e..87837fd82 100644
--- a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala
+++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala
@@ -238,7 +238,7 @@ object messages {
import core.Flags._
val maxDist = 3
val decls = site.decls.flatMap { sym =>
- if (sym.is(Synthetic | PrivateOrLocal) || sym.isConstructor) Nil
+ if (sym.flagsUNSAFE.is(Synthetic | PrivateOrLocal) || sym.isConstructor) Nil
else List((sym.name.show, sym))
}
@@ -617,7 +617,7 @@ object messages {
|"""
}
- case class WrongNumberOfTypeArgs(fntpe: Type, expectedArgs: List[TypeParamInfo], actual: List[untpd.Tree])(implicit ctx: Context)
+ case class WrongNumberOfTypeArgs(fntpe: Type, expectedArgs: List[ParamInfo], actual: List[untpd.Tree])(implicit ctx: Context)
extends Message(WrongNumberOfTypeArgsID) {
val kind = "Syntax"
@@ -625,7 +625,7 @@ object messages {
private val actualCount = actual.length
private val msgPrefix = if (actualCount > expectedCount) "Too many" else "Not enough"
- //TODO add def simpleParamName to TypeParamInfo
+ //TODO add def simpleParamName to ParamInfo
private val expectedArgString = fntpe
.widen.typeParams
.map(_.paramName.unexpandedName.show)
diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala
index 082a80b58..8d704f9a2 100644
--- a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala
+++ b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala
@@ -286,7 +286,7 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder
def apiDef(sym: TermSymbol): api.Def = {
def paramLists(t: Type, start: Int = 0): List[api.ParameterList] = t match {
- case pt: PolyType =>
+ case pt: TypeLambda =>
assert(start == 0)
paramLists(pt.resultType)
case mt @ MethodTpe(pnames, ptypes, restpe) =>
@@ -311,8 +311,8 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder
}
val tparams = sym.info match {
- case pt: PolyType =>
- (pt.paramNames, pt.paramBounds).zipped.map((pname, pbounds) =>
+ case pt: TypeLambda =>
+ (pt.paramNames, pt.paramInfos).zipped.map((pname, pbounds) =>
apiTypeParameter(pname.toString, 0, pbounds.lo, pbounds.hi))
case _ =>
Nil
@@ -385,9 +385,9 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder
val apiTycon = simpleType(tycon)
val apiArgs = args.map(processArg)
new api.Parameterized(apiTycon, apiArgs.toArray)
- case PolyType(tparams, res) =>
- val apiTparams = tparams.map(apiTypeParameter)
- val apiRes = apiType(res)
+ case tl: TypeLambda =>
+ val apiTparams = tl.typeParams.map(apiTypeParameter)
+ val apiRes = apiType(tl.resType)
new api.Polymorphic(apiRes, apiTparams.toArray)
case rt: RefinedType =>
val name = rt.refinedName.toString
@@ -460,7 +460,7 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder
new api.Annotated(apiType(tpe), Array(apiAnnotation(annot)))
case tp: ThisType =>
apiThis(tp.cls)
- case tp: ParamType =>
+ case tp: ParamRef =>
// TODO: Distinguishing parameters based on their names alone is not enough,
// the binder is also needed (at least for type lambdas).
new api.ParameterRef(tp.paramName.toString)
@@ -497,9 +497,9 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder
new api.Singleton(new api.Path(pathComponents.toArray.reverse ++ Array(Constants.thisPath)))
}
- def apiTypeParameter(tparam: TypeParamInfo): api.TypeParameter =
+ def apiTypeParameter(tparam: ParamInfo): api.TypeParameter =
apiTypeParameter(tparam.paramName.toString, tparam.paramVariance,
- tparam.paramBounds.lo, tparam.paramBounds.hi)
+ tparam.paramInfo.bounds.lo, tparam.paramInfo.bounds.hi)
def apiTypeParameter(name: String, variance: Int, lo: Type, hi: Type): api.TypeParameter =
new api.TypeParameter(name, Array(), Array(), apiVariance(variance),
diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala
index fefa63f6f..0a061c841 100644
--- a/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala
+++ b/compiler/src/dotty/tools/dotc/sbt/ExtractDependencies.scala
@@ -256,9 +256,7 @@ private class ExtractDependenciesCollector(implicit val ctx: Context) extends tp
traverse(tp.underlying)
case tp: ConstantType =>
traverse(tp.underlying)
- case tp: MethodParam =>
- traverse(tp.underlying)
- case tp: PolyParam =>
+ case tp: ParamRef =>
traverse(tp.underlying)
case _ =>
traverseChildren(tp)
diff --git a/compiler/src/dotty/tools/dotc/transform/CollectEntryPoints.scala b/compiler/src/dotty/tools/dotc/transform/CollectEntryPoints.scala
index 9f1e42e31..e82be4378 100644
--- a/compiler/src/dotty/tools/dotc/transform/CollectEntryPoints.scala
+++ b/compiler/src/dotty/tools/dotc/transform/CollectEntryPoints.scala
@@ -88,7 +88,7 @@ class CollectEntryPoints extends MiniPhaseTransform {
case t: PolyType =>
fail("main methods cannot be generic.")
case t: MethodType =>
- if (t.resultType :: t.paramTypes exists (_.typeSymbol.isAbstractType))
+ if (t.resultType :: t.paramInfos 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 59da78590..839552799 100644
--- a/compiler/src/dotty/tools/dotc/transform/ElimByName.scala
+++ b/compiler/src/dotty/tools/dotc/transform/ElimByName.scala
@@ -93,7 +93,7 @@ class ElimByName extends MiniPhaseTransform with InfoTransformer { thisTransform
}
val mt @ MethodType(_) = tree.fun.tpe.widen
- val args1 = tree.args.zipWithConserve(mt.paramTypes)(transformArg)
+ val args1 = tree.args.zipWithConserve(mt.paramInfos)(transformArg)
cpy.Apply(tree)(tree.fun, args1)
}
diff --git a/compiler/src/dotty/tools/dotc/transform/ElimErasedValueType.scala b/compiler/src/dotty/tools/dotc/transform/ElimErasedValueType.scala
index 24c8cdc8d..48be02fa1 100644
--- a/compiler/src/dotty/tools/dotc/transform/ElimErasedValueType.scala
+++ b/compiler/src/dotty/tools/dotc/transform/ElimErasedValueType.scala
@@ -44,9 +44,9 @@ class ElimErasedValueType extends MiniPhaseTransform with InfoTransformer {
case ErasedValueType(_, underlying) =>
elimEVT(underlying)
case tp: MethodType =>
- val paramTypes = tp.paramTypes.mapConserve(elimEVT)
+ val paramTypes = tp.paramInfos.mapConserve(elimEVT)
val retType = elimEVT(tp.resultType)
- tp.derivedMethodType(tp.paramNames, paramTypes, retType)
+ tp.derivedLambdaType(tp.paramNames, paramTypes, retType)
case _ =>
tp
}
diff --git a/compiler/src/dotty/tools/dotc/transform/ElimRepeated.scala b/compiler/src/dotty/tools/dotc/transform/ElimRepeated.scala
index ae3259509..683c8ac38 100644
--- a/compiler/src/dotty/tools/dotc/transform/ElimRepeated.scala
+++ b/compiler/src/dotty/tools/dotc/transform/ElimRepeated.scala
@@ -55,9 +55,9 @@ class ElimRepeated extends MiniPhaseTransform with InfoTransformer with Annotati
val last = paramTypes.last.underlyingIfRepeated(tp.isJava)
paramTypes.init :+ last
} else paramTypes
- tp.derivedMethodType(paramNames, paramTypes1, resultType1)
+ tp.derivedLambdaType(paramNames, paramTypes1, resultType1)
case tp: PolyType =>
- tp.derivedPolyType(tp.paramNames, tp.paramBounds, elimRepeated(tp.resultType))
+ tp.derivedLambdaType(tp.paramNames, tp.paramInfos, elimRepeated(tp.resultType))
case tp =>
tp
}
@@ -139,10 +139,10 @@ class ElimRepeated extends MiniPhaseTransform with InfoTransformer with Annotati
/** Convert type from Scala to Java varargs method */
private def toJavaVarArgs(tp: Type)(implicit ctx: Context): Type = tp match {
case tp: PolyType =>
- tp.derivedPolyType(tp.paramNames, tp.paramBounds, toJavaVarArgs(tp.resultType))
+ tp.derivedLambdaType(tp.paramNames, tp.paramInfos, toJavaVarArgs(tp.resultType))
case tp: MethodType =>
- val inits :+ last = tp.paramTypes
+ val inits :+ last = tp.paramInfos
val last1 = last.underlyingIfRepeated(isJava = true)
- tp.derivedMethodType(tp.paramNames, inits :+ last1, tp.resultType)
+ tp.derivedLambdaType(tp.paramNames, inits :+ last1, tp.resultType)
}
}
diff --git a/compiler/src/dotty/tools/dotc/transform/Erasure.scala b/compiler/src/dotty/tools/dotc/transform/Erasure.scala
index f9c7a8e1e..d64120085 100644
--- a/compiler/src/dotty/tools/dotc/transform/Erasure.scala
+++ b/compiler/src/dotty/tools/dotc/transform/Erasure.scala
@@ -461,12 +461,12 @@ object Erasure extends TypeTestsCasts{
case mt: MethodType =>
val outers = outer.args(fun.asInstanceOf[tpd.Tree]) // can't use fun1 here because its type is already erased
var args0 = outers ::: args ++ protoArgs(pt)
- if (args0.length > MaxImplementedFunctionArity && mt.paramTypes.length == 1) {
+ if (args0.length > MaxImplementedFunctionArity && mt.paramInfos.length == 1) {
val bunchedArgs = untpd.JavaSeqLiteral(args0, TypeTree(defn.ObjectType))
.withType(defn.ArrayOf(defn.ObjectType))
args0 = bunchedArgs :: Nil
}
- val args1 = args0.zipWithConserve(mt.paramTypes)(typedExpr)
+ val args1 = args0.zipWithConserve(mt.paramInfos)(typedExpr)
untpd.cpy.Apply(tree)(fun1, args1) withType mt.resultType
case _ =>
throw new MatchError(i"tree $tree has unexpected type of function ${fun1.tpe.widen}, was ${fun.typeOpt.widen}")
@@ -547,8 +547,8 @@ object Erasure extends TypeTestsCasts{
case SAMType(sam) =>
val implType = meth.tpe.widen
- val List(implParamTypes) = implType.paramTypess
- val List(samParamTypes) = sam.info.paramTypess
+ val List(implParamTypes) = implType.paramInfoss
+ val List(samParamTypes) = sam.info.paramInfoss
val implResultType = implType.resultType
val samResultType = sam.info.resultType
@@ -698,8 +698,8 @@ object Erasure extends TypeTestsCasts{
val rhs = paramss.foldLeft(sel)((fun, vparams) =>
fun.tpe.widen match {
case mt: MethodType =>
- Apply(fun, (vparams, mt.paramTypes).zipped.map(adapt(_, _, untpd.EmptyTree)))
- case a =>
+ Apply(fun, (vparams, mt.paramInfos).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/ExplicitOuter.scala b/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala
index f17808e62..a6e643992 100644
--- a/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala
+++ b/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala
@@ -331,7 +331,7 @@ object ExplicitOuter {
def addParam(cls: ClassSymbol, tp: Type): Type =
if (hasOuterParam(cls)) {
val mt @ MethodTpe(pnames, ptypes, restpe) = tp
- mt.derivedMethodType(
+ mt.derivedLambdaType(
nme.OUTER :: pnames, cls.owner.enclosingClass.typeRef :: ptypes, restpe)
} else tp
diff --git a/compiler/src/dotty/tools/dotc/transform/FullParameterization.scala b/compiler/src/dotty/tools/dotc/transform/FullParameterization.scala
index 0cb453b4c..d76a41946 100644
--- a/compiler/src/dotty/tools/dotc/transform/FullParameterization.scala
+++ b/compiler/src/dotty/tools/dotc/transform/FullParameterization.scala
@@ -107,13 +107,13 @@ trait FullParameterization {
val firstArgType = if (liftThisType) thisParamType & clazz.thisType else thisParamType
MethodType(nme.SELF :: Nil)(
mt => firstArgType :: Nil,
- mt => mapClassParams(origResult).substThisUnlessStatic(clazz, MethodParam(mt, 0)))
+ mt => mapClassParams(origResult).substThisUnlessStatic(clazz, mt.newParamRef(0)))
}
/** Replace class type parameters by the added type parameters of the polytype `pt` */
def mapClassParams(tp: Type, pt: PolyType): Type = {
val classParamsRange = (mtparamCount until mtparamCount + ctparams.length).toList
- tp.substDealias(ctparams, classParamsRange map (PolyParam(pt, _)))
+ tp.substDealias(ctparams, classParamsRange map (TypeParamRef(pt, _)))
}
/** The bounds for the added type parameters of the polytype `pt` */
@@ -122,14 +122,14 @@ trait FullParameterization {
info match {
case info: PolyType =>
- PolyType(info.paramNames ++ ctnames, info.variances ++ ctvariances)(
+ PolyType(info.paramNames ++ ctnames)(
pt =>
- (info.paramBounds.map(mapClassParams(_, pt).bounds) ++
+ (info.paramInfos.map(mapClassParams(_, pt).bounds) ++
mappedClassBounds(pt)).mapConserve(_.subst(info, pt).bounds),
pt => resultType(mapClassParams(_, pt)).subst(info, pt))
case _ =>
if (ctparams.isEmpty) resultType(identity)
- else PolyType(ctnames, ctvariances)(mappedClassBounds, pt => resultType(mapClassParams(_, pt)))
+ else PolyType(ctnames)(mappedClassBounds, pt => resultType(mapClassParams(_, pt)))
}
}
@@ -233,7 +233,7 @@ 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 = (originalDef.vparamss, fun.tpe.paramTypess).zipped.map((vparams, paramTypes) =>
+ val args = (originalDef.vparamss, fun.tpe.paramInfoss).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)
@@ -256,7 +256,7 @@ object FullParameterization {
case MethodTpe(nme.SELF :: Nil, _, restpe) =>
restpe.ensureMethodic.signature
case info @ MethodTpe(nme.SELF :: otherNames, thisType :: otherTypes, restpe) =>
- info.derivedMethodType(otherNames, otherTypes, restpe).signature
+ info.derivedLambdaType(otherNames, otherTypes, restpe).signature
case _ =>
Signature.NotAMethod
}
diff --git a/compiler/src/dotty/tools/dotc/transform/FunctionalInterfaces.scala b/compiler/src/dotty/tools/dotc/transform/FunctionalInterfaces.scala
index 5fd89314a..bde902152 100644
--- a/compiler/src/dotty/tools/dotc/transform/FunctionalInterfaces.scala
+++ b/compiler/src/dotty/tools/dotc/transform/FunctionalInterfaces.scala
@@ -31,8 +31,8 @@ class FunctionalInterfaces extends MiniPhaseTransform {
val maxArgsCount = 2
def shouldSpecialize(m: MethodType)(implicit ctx: Context) =
- (m.paramTypes.size <= maxArgsCount) &&
- m.paramTypes.forall(x => allowedArgumentTypes.contains(x.typeSymbol)) &&
+ (m.paramInfos.size <= maxArgsCount) &&
+ m.paramInfos.forall(x => allowedArgumentTypes.contains(x.typeSymbol)) &&
allowedReturnTypes.contains(m.resultType.typeSymbol)
val functionName = "JFunction".toTermName
@@ -67,7 +67,7 @@ class FunctionalInterfaces extends MiniPhaseTransform {
val names = ctx.atPhase(ctx.erasurePhase) {
implicit ctx => functionSymbol.typeParams.map(_.name)
}
- val interfaceName = (functionName ++ m.paramTypes.length.toString).specializedFor(m.paramTypes ::: m.resultType :: Nil, names, Nil, Nil)
+ val interfaceName = (functionName ++ m.paramInfos.length.toString).specializedFor(m.paramInfos ::: m.resultType :: Nil, names, Nil, Nil)
// symbols loaded from classpath aren't defined in periods earlier than when they where loaded
val interface = ctx.withPhase(ctx.typerPhase).getClassIfDefined(functionPackage ++ interfaceName)
diff --git a/compiler/src/dotty/tools/dotc/transform/MixinOps.scala b/compiler/src/dotty/tools/dotc/transform/MixinOps.scala
index 9f7ceeaed..d91522c25 100644
--- a/compiler/src/dotty/tools/dotc/transform/MixinOps.scala
+++ b/compiler/src/dotty/tools/dotc/transform/MixinOps.scala
@@ -72,7 +72,7 @@ class MixinOps(cls: ClassSymbol, thisTransform: DenotTransformer)(implicit ctx:
def hasPrimitiveMissMatch(tp1: Type, tp2: Type): Boolean = (tp1, tp2) match {
case (tp1: MethodicType, tp2: MethodicType) =>
hasPrimitiveMissMatch(tp1.resultType, tp2.resultType) ||
- tp1.paramTypess.flatten.zip(tp1.paramTypess.flatten).exists(args => hasPrimitiveMissMatch(args._1, args._2))
+ tp1.paramInfoss.flatten.zip(tp1.paramInfoss.flatten).exists(args => hasPrimitiveMissMatch(args._1, args._2))
case _ =>
def isPrimitiveOrValueClass(sym: Symbol): Boolean = sym.isPrimitiveValueClass || sym.isValueClass
isPrimitiveOrValueClass(tp1.typeSymbol) ^ isPrimitiveOrValueClass(tp2.typeSymbol)
diff --git a/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala b/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala
index 197d18374..dbc7666f7 100644
--- a/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala
+++ b/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala
@@ -1766,7 +1766,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {
def applyMethodTypes(method: Type): Extractor = {
val whole = method.finalResultType
- method.paramTypess.head match {
+ method.paramInfoss.head match {
case init :+ last if last.isRepeatedParam => newExtractor(whole, init, repeatedFromVarargs(last))
case tps => newExtractor(whole, tps, NoRepeated)
}
diff --git a/compiler/src/dotty/tools/dotc/transform/PostTyper.scala b/compiler/src/dotty/tools/dotc/transform/PostTyper.scala
index 8dff58dea..9821757e8 100644
--- a/compiler/src/dotty/tools/dotc/transform/PostTyper.scala
+++ b/compiler/src/dotty/tools/dotc/transform/PostTyper.scala
@@ -2,7 +2,7 @@ package dotty.tools.dotc
package transform
import dotty.tools.dotc.transform.TreeTransforms.{TransformerInfo, TreeTransform, TreeTransformer}
-import dotty.tools.dotc.ast.{Trees, tpd}
+import dotty.tools.dotc.ast.{Trees, tpd, untpd}
import scala.collection.{ mutable, immutable }
import ValueClasses._
import scala.annotation.tailrec
@@ -258,15 +258,15 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisTran
)
case Import(expr, selectors) =>
val exprTpe = expr.tpe
- def checkIdent(ident: Ident): Unit = {
+ def checkIdent(ident: untpd.Ident): Unit = {
val name = ident.name.asTermName.encode
if (name != nme.WILDCARD && !exprTpe.member(name).exists && !exprTpe.member(name.toTypeName).exists)
ctx.error(s"${ident.name} is not a member of ${expr.show}", ident.pos)
}
selectors.foreach {
- case ident: Ident => checkIdent(ident)
- case Thicket((ident: Ident) :: _) => checkIdent(ident)
- case _ =>
+ case ident: untpd.Ident => checkIdent(ident)
+ case Thicket((ident: untpd.Ident) :: _) => checkIdent(ident)
+ case _ =>
}
super.transform(tree)
case tree =>
diff --git a/compiler/src/dotty/tools/dotc/transform/ShortcutImplicits.scala b/compiler/src/dotty/tools/dotc/transform/ShortcutImplicits.scala
index b5469610f..1a530b95c 100644
--- a/compiler/src/dotty/tools/dotc/transform/ShortcutImplicits.scala
+++ b/compiler/src/dotty/tools/dotc/transform/ShortcutImplicits.scala
@@ -82,8 +82,8 @@ class ShortcutImplicits extends MiniPhase with IdentityDenotTransformer { thisTr
* @return The type of the `apply` member of `implicit Ts => R`.
*/
private def directInfo(info: Type)(implicit ctx: Context): Type = info match {
- case info: PolyType => info.derivedPolyType(resType = directInfo(info.resultType))
- case info: MethodType => info.derivedMethodType(resType = directInfo(info.resultType))
+ case info: PolyType => info.derivedLambdaType(resType = directInfo(info.resultType))
+ case info: MethodType => info.derivedLambdaType(resType = directInfo(info.resultType))
case info: ExprType => directInfo(info.resultType)
case info => info.member(nme.apply).info
}
diff --git a/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala b/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala
index 3c11827fc..728c1696b 100644
--- a/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala
+++ b/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala
@@ -178,9 +178,9 @@ class SuperAccessors(thisTransformer: DenotTransformer) {
val accType = {
def accTypeOf(tpe: Type): Type = tpe match {
case tpe: PolyType =>
- tpe.derivedPolyType(tpe.paramNames, tpe.paramBounds, accTypeOf(tpe.resultType))
+ tpe.derivedLambdaType(tpe.paramNames, tpe.paramInfos, accTypeOf(tpe.resultType))
case _ =>
- MethodType(receiverType :: Nil)(mt => tpe.substThis(sym.owner.asClass, MethodParam(mt, 0)))
+ MethodType(receiverType :: Nil)(mt => tpe.substThis(sym.owner.asClass, mt.newParamRef(0)))
}
accTypeOf(sym.info)
}
@@ -230,9 +230,9 @@ class SuperAccessors(thisTransformer: DenotTransformer) {
else clazz.classInfo.selfType
def accTypeOf(tpe: Type): Type = tpe match {
case tpe: PolyType =>
- tpe.derivedPolyType(tpe.paramNames, tpe.paramBounds, accTypeOf(tpe.resultType))
+ tpe.derivedLambdaType(tpe.paramNames, tpe.paramInfos, accTypeOf(tpe.resultType))
case _ =>
- MethodType(receiverType :: Nil)(mt => tpe.substThis(sym.owner.asClass, MethodParam(mt, 0)))
+ MethodType(receiverType :: Nil)(mt => tpe.substThis(sym.owner.asClass, mt.newParamRef(0)))
}
val accType = accTypeOf(sym.info)
val protectedAccessor = clazz.info.decl(accName).suchThat(_.signature == accType.signature).symbol orElse {
diff --git a/compiler/src/dotty/tools/dotc/transform/TailRec.scala b/compiler/src/dotty/tools/dotc/transform/TailRec.scala
index aa0845605..8a695bf22 100644
--- a/compiler/src/dotty/tools/dotc/transform/TailRec.scala
+++ b/compiler/src/dotty/tools/dotc/transform/TailRec.scala
@@ -325,6 +325,10 @@ class TailRec extends MiniPhaseTransform with DenotTransformer with FullParamete
else
rewriteApply(tree, meth)
+ case TypeApply(fun, targs) =>
+ val meth = fun.symbol
+ rewriteApply(tree, meth)
+
case tree@Block(stats, expr) =>
tpd.cpy.Block(tree)(
noTailTransforms(stats),
diff --git a/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala b/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala
index 51e2469b2..ebb5b605b 100644
--- a/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala
+++ b/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala
@@ -139,13 +139,13 @@ class TreeChecker extends Phase with SymTransformer {
class Checker(phasesToCheck: Seq[Phase]) extends ReTyper with Checking {
val nowDefinedSyms = new mutable.HashSet[Symbol]
- val everDefinedSyms = new mutable.HashMap[Symbol, Tree]
+ val everDefinedSyms = new mutable.HashMap[Symbol, untpd.Tree]
// don't check value classes after typer, as the constraint about constructors doesn't hold after transform
override def checkDerivedValueClass(clazz: Symbol, stats: List[Tree])(implicit ctx: Context) = ()
def withDefinedSym[T](tree: untpd.Tree)(op: => T)(implicit ctx: Context): T = tree match {
- case tree: DefTree =>
+ case tree: untpd.DefTree =>
val sym = tree.symbol
assert(isValidJVMName(sym.name), s"${sym.fullName} name is invalid on jvm")
everDefinedSyms.get(sym) match {
@@ -160,7 +160,7 @@ class TreeChecker extends Phase with SymTransformer {
if (ctx.settings.YcheckMods.value) {
tree match {
- case t: MemberDef =>
+ case t: untpd.MemberDef =>
if (t.name ne sym.name) ctx.warning(s"symbol ${sym.fullName} name doesn't correspond to AST: ${t}")
// todo: compare trees inside annotations
case _ =>
@@ -287,7 +287,7 @@ class TreeChecker extends Phase with SymTransformer {
res
}
- /** Check that PolyParams and MethodParams refer to an enclosing type */
+ /** Check that TypeParamRefs and MethodParams refer to an enclosing type */
def checkNoOrphans(tp: Type)(implicit ctx: Context) = new TypeMap() {
val definedBinders = mutable.Set[Type]()
def apply(tp: Type): Type = {
@@ -296,7 +296,7 @@ class TreeChecker extends Phase with SymTransformer {
definedBinders += tp
mapOver(tp)
definedBinders -= tp
- case tp: ParamType =>
+ case tp: ParamRef =>
assert(definedBinders.contains(tp.binder), s"orphan param: $tp")
case tp: TypeVar =>
apply(tp.underlying)
diff --git a/compiler/src/dotty/tools/dotc/transform/VCInlineMethods.scala b/compiler/src/dotty/tools/dotc/transform/VCInlineMethods.scala
index ddd414417..ab24e1720 100644
--- a/compiler/src/dotty/tools/dotc/transform/VCInlineMethods.scala
+++ b/compiler/src/dotty/tools/dotc/transform/VCInlineMethods.scala
@@ -86,7 +86,7 @@ class VCInlineMethods extends MiniPhaseTransform with IdentityDenotTransformer {
* by a call to the corresponding extension method, otherwise return it as is.
*/
private def rewireIfNeeded(tree: Tree)(implicit ctx: Context) = tree.tpe.widen match {
- case tp: MethodOrPoly =>
+ case tp: LambdaType =>
tree // The rewiring will be handled by a fully-applied parent node
case _ =>
if (isMethodWithExtension(tree.symbol))
diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala
index 5dcf16b62..4e43e429b 100644
--- a/compiler/src/dotty/tools/dotc/typer/Applications.scala
+++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala
@@ -34,7 +34,7 @@ object Applications {
def extractorMember(tp: Type, name: Name)(implicit ctx: Context) = {
def isPossibleExtractorType(tp: Type) = tp match {
- case _: MethodType | _: PolyType => false
+ case _: MethodOrPoly => false
case _ => true
}
tp.member(name).suchThat(d => isPossibleExtractorType(d.info))
@@ -195,7 +195,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
}
/** The function's type after widening and instantiating polytypes
- * with polyparams in constraint set
+ * with TypeParamRefs in constraint set
*/
val methType = funType.widen match {
case funType: MethodType => funType
@@ -217,7 +217,14 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
// apply the result type constraint, unless method type is dependent
val resultApprox = resultTypeApprox(methType)
val savedConstraint = ctx.typerState.constraint
- if (!constrainResult(resultApprox, resultType))
+ if (!resultApprox.isInstanceOf[PolyType] &&
+ // temporary fix before #2121 is in. The problem here is that errors in the code
+ // can lead to the result type begin higher-kinded. Then normalize gets confused
+ // and we end up with an assertion violation "s"inconsistent: no typevars were
+ // added to committable constraint". Once we distinguish between type lambdas
+ // and polytypes again this should hopefully become unnecessary. The error
+ // was triggered by neg/enums.scala.
+ !constrainResult(resultApprox, resultType))
if (ctx.typerState.isCommittable)
// defer the problem until after the application;
// it might be healed by an implicit conversion
@@ -225,7 +232,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
else
fail(err.typeMismatchMsg(methType.resultType, resultType))
// match all arguments with corresponding formal parameters
- matchArgs(orderedArgs, methType.paramTypes, 0)
+ matchArgs(orderedArgs, methType.paramInfos, 0)
case _ =>
if (methType.isError) ok = false
else fail(s"$methString does not take parameters")
@@ -388,7 +395,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
def addTyped(arg: Arg, formal: Type): Type => Type = {
addArg(typedArg(arg, formal), formal)
if (methodType.isParamDependent)
- _.substParam(MethodParam(methodType, n), typeOfArg(arg))
+ _.substParam(methodType.newParamRef(n), typeOfArg(arg))
else
identity
}
@@ -756,7 +763,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
val typedFn = typedExpr(tree.fun, PolyProto(typedArgs.tpes, pt))
typedFn.tpe.widen match {
case pt: PolyType =>
- if (typedArgs.length <= pt.paramBounds.length && !isNamed)
+ if (typedArgs.length <= pt.paramInfos.length && !isNamed)
if (typedFn.symbol == defn.Predef_classOf && typedArgs.nonEmpty) {
val arg = typedArgs.head
checkClassType(arg.tpe, arg.pos, traitReq = false, stablePrefixReq = false)
@@ -876,8 +883,8 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
}
unapplyFn.tpe.widen match {
- case mt: MethodType if mt.paramTypes.length == 1 =>
- val unapplyArgType = mt.paramTypes.head
+ case mt: MethodType if mt.paramInfos.length == 1 =>
+ val unapplyArgType = mt.paramInfos.head
unapp.println(i"unapp arg tpe = $unapplyArgType, pt = $selType")
val ownType =
if (selType <:< unapplyArgType) {
@@ -1049,17 +1056,17 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
case _ => if (tp.isRepeatedParam) tp.argTypesHi.head else tp
}
val formals1 =
- if (tp1.isVarArgsMethod && tp2.isVarArgsMethod) tp1.paramTypes map repeatedToSingle
- else tp1.paramTypes
+ if (tp1.isVarArgsMethod && tp2.isVarArgsMethod) tp1.paramInfos map repeatedToSingle
+ else tp1.paramInfos
isApplicable(alt2, formals1, WildcardType) ||
- tp1.paramTypes.isEmpty && tp2.isInstanceOf[MethodOrPoly]
+ tp1.paramInfos.isEmpty && tp2.isInstanceOf[LambdaType]
case tp1: PolyType => // (2)
val tparams = ctx.newTypeParams(alt1.symbol, tp1.paramNames, EmptyFlags, tp1.instantiateBounds)
isAsSpecific(alt1, tp1.instantiate(tparams map (_.typeRef)), alt2, tp2)
case _ => // (3)
tp2 match {
case tp2: MethodType => true // (3a)
- case tp2: PolyType if tp2.isPolymorphicMethodType => true // (3a)
+ case tp2: PolyType if tp2.resultType.isInstanceOf[MethodType] => true // (3a)
case tp2: PolyType => // (3b)
val nestedCtx = ctx.fresh.setExploreTyperState
@@ -1118,7 +1125,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
case mt: ImplicitMethodType =>
resultTypeApprox(mt)
case pt: PolyType =>
- pt.derivedPolyType(pt.paramNames, pt.paramBounds, stripImplicit(pt.resultType))
+ pt.derivedLambdaType(pt.paramNames, pt.paramInfos, stripImplicit(pt.resultType))
case _ =>
tp
}
@@ -1277,10 +1284,9 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
case x => x
}
- def sizeFits(alt: TermRef, tp: Type): Boolean = tp match {
- case tp: PolyType => sizeFits(alt, tp.resultType)
+ def sizeFits(alt: TermRef, tp: Type): Boolean = tp.stripPoly match {
case tp: MethodType =>
- val ptypes = tp.paramTypes
+ val ptypes = tp.paramInfos
val numParams = ptypes.length
def isVarArgs = ptypes.nonEmpty && ptypes.last.isRepeatedParam
def hasDefault = alt.symbol.hasDefaultParams
@@ -1405,12 +1411,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
recur(altFormals.map(_.tail), args1)
case _ =>
}
- def paramTypes(alt: Type): List[Type] = alt match {
- case mt: MethodType => mt.paramTypes
- case mt: PolyType => paramTypes(mt.resultType)
- case _ => Nil
- }
- recur(alts.map(alt => paramTypes(alt.widen)), pt.args)
+ recur(alts.map(_.widen.firstParamTypes), pt.args)
}
private def harmonizeWith[T <: AnyRef](ts: List[T])(tpe: T => Type, adapt: (T, Type) => T)(implicit ctx: Context): List[T] = {
diff --git a/compiler/src/dotty/tools/dotc/typer/Checking.scala b/compiler/src/dotty/tools/dotc/typer/Checking.scala
index b43391592..5d1c44efc 100644
--- a/compiler/src/dotty/tools/dotc/typer/Checking.scala
+++ b/compiler/src/dotty/tools/dotc/typer/Checking.scala
@@ -50,12 +50,12 @@ object Checking {
arg.pos.focus)
}
- /** Check that type arguments `args` conform to corresponding bounds in `poly`
+ /** Check that type arguments `args` conform to corresponding bounds in `tl`
* Note: This does not check the bounds of AppliedTypeTrees. These
* are handled by method checkBounds in FirstTransform
*/
- def checkBounds(args: List[tpd.Tree], poly: PolyType)(implicit ctx: Context): Unit =
- checkBounds(args, poly.paramBounds, _.substParams(poly, _))
+ def checkBounds(args: List[tpd.Tree], tl: TypeLambda)(implicit ctx: Context): Unit =
+ checkBounds(args, tl.paramInfos, _.substParams(tl, _))
/** Check applied type trees for well-formedness. This means
* - all arguments are within their corresponding bounds
@@ -69,20 +69,20 @@ object Checking {
// If `args` is a list of named arguments, return corresponding type parameters,
// otherwise return type parameters unchanged
val tparams = tycon.tpe.typeParams
- def argNamed(tparam: TypeParamInfo) = args.find {
+ def argNamed(tparam: ParamInfo) = args.find {
case NamedArg(name, _) => name == tparam.paramName
case _ => false
}.getOrElse(TypeTree(tparam.paramRef))
val orderedArgs = if (hasNamedArg(args)) tparams.map(argNamed) else args
- val bounds = tparams.map(_.paramBoundsAsSeenFrom(tycon.tpe))
+ val bounds = tparams.map(_.paramInfoAsSeenFrom(tycon.tpe).bounds)
def instantiate(bound: Type, args: List[Type]) =
- bound.LambdaAbstract(tparams).appliedTo(args)
+ HKTypeLambda.fromParams(tparams, bound).appliedTo(args)
checkBounds(orderedArgs, bounds, instantiate)
def checkWildcardHKApply(tp: Type, pos: Position): Unit = tp match {
case tp @ HKApply(tycon, args) if args.exists(_.isInstanceOf[TypeBounds]) =>
tycon match {
- case tycon: PolyType =>
+ case tycon: TypeLambda =>
ctx.errorOrMigrationWarning(
ex"unreducible application of higher-kinded type $tycon to wildcard arguments",
pos)
@@ -348,12 +348,23 @@ object Checking {
/** Check the type signature of the symbol `M` defined by `tree` does not refer
* to a private type or value which is invisible at a point where `M` is still
- * visible. As an exception, we allow references to type aliases if the underlying
- * type of the alias is not a leak. So type aliases are transparent as far as
- * leak testing is concerned.
+ * visible.
+ *
+ * As an exception, we allow references to type aliases if the underlying
+ * type of the alias is not a leak, and if `sym` is not a type. The rationale
+ * for this is that the inferred type of a term symbol might contain leaky
+ * aliases which should be removed (see leak-inferred.scala for an example),
+ * but a type symbol definition will not contain leaky aliases unless the
+ * user wrote them, so we can ask the user to change his definition. The more
+ * practical reason for not transforming types is that `checkNoPrivateLeaks`
+ * can force a lot of denotations, and this restriction means that we never
+ * need to run `TypeAssigner#avoidPrivateLeaks` on type symbols when
+ * unpickling, which avoids some issues related to forcing order.
+ *
+ * See i997.scala for negative tests, and i1130.scala for a case where it
+ * matters that we transform leaky aliases away.
+ *
* @return The `info` of `sym`, with problematic aliases expanded away.
- * See i997.scala for tests, i1130.scala for a case where it matters that we
- * transform leaky aliases away.
*/
def checkNoPrivateLeaks(sym: Symbol, pos: Position)(implicit ctx: Context): Type = {
class NotPrivate extends TypeMap {
@@ -388,7 +399,7 @@ object Checking {
tp
}
else mapOver(tp)
- if ((errors ne prevErrors) && tp.info.isAlias) {
+ if ((errors ne prevErrors) && !sym.isType && tp.info.isAlias) {
// try to dealias to avoid a leak error
val savedErrors = errors
errors = prevErrors
@@ -400,8 +411,14 @@ object Checking {
case tp: ClassInfo =>
tp.derivedClassInfo(
prefix = apply(tp.prefix),
- classParents = tp.parentsWithArgs.map(p =>
- apply(p).underlyingClassRef(refinementOK = false).asInstanceOf[TypeRef]))
+ classParents =
+ tp.parentsWithArgs.map { p =>
+ apply(p).underlyingClassRef(refinementOK = false) match {
+ case ref: TypeRef => ref
+ case _ => defn.ObjectType // can happen if class files are missing
+ }
+ }
+ )
case _ =>
mapOver(tp)
}
diff --git a/compiler/src/dotty/tools/dotc/typer/Dynamic.scala b/compiler/src/dotty/tools/dotc/typer/Dynamic.scala
index 000cfd026..25fca546e 100644
--- a/compiler/src/dotty/tools/dotc/typer/Dynamic.scala
+++ b/compiler/src/dotty/tools/dotc/typer/Dynamic.scala
@@ -150,7 +150,7 @@ trait Dynamic { self: Typer with Applications =>
|Structural types only support methods taking up to ${Definitions.MaxStructuralMethodArity} arguments""")
else {
def issueError(msgFn: String => String): Unit = ctx.error(msgFn(""), tree.pos)
- val ctags = tpe.paramTypes.map(pt =>
+ val ctags = tpe.paramInfos.map(pt =>
inferImplicitArg(defn.ClassTagType.appliedTo(pt :: Nil), issueError, tree.pos.endPos))
structuralCall(nme.selectDynamicMethod, ctags).asInstance(tpe.toFunctionType())
}
diff --git a/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala b/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala
index a1690955f..6c72c16e0 100644
--- a/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala
+++ b/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala
@@ -46,7 +46,7 @@ object ErrorReporting {
errorMsg(ex.toMessage, ctx)
}
- def wrongNumberOfTypeArgs(fntpe: Type, expectedArgs: List[TypeParamInfo], actual: List[untpd.Tree], pos: Position)(implicit ctx: Context) =
+ def wrongNumberOfTypeArgs(fntpe: Type, expectedArgs: List[ParamInfo], actual: List[untpd.Tree], pos: Position)(implicit ctx: Context) =
errorType(WrongNumberOfTypeArgs(fntpe, expectedArgs, actual)(ctx), pos)
class Errors(implicit ctx: Context) {
@@ -74,7 +74,7 @@ object ErrorReporting {
def anonymousTypeMemberStr(tpe: Type) = {
val kind = tpe match {
case _: TypeBounds => "type with bounds"
- case _: PolyType | _: MethodType => "method"
+ case _: MethodOrPoly => "method"
case _ => "value of type"
}
em"$kind $tpe"
@@ -105,9 +105,9 @@ object ErrorReporting {
def whyNoMatchStr(found: Type, expected: Type) = {
def dropJavaMethod(tp: Type): Type = tp match {
case tp: PolyType =>
- tp.derivedPolyType(resType = dropJavaMethod(tp.resultType))
+ tp.derivedLambdaType(resType = dropJavaMethod(tp.resultType))
case tp: JavaMethodType =>
- MethodType(tp.paramNames, tp.paramTypes, dropJavaMethod(tp.resultType))
+ MethodType(tp.paramNames, tp.paramInfos, dropJavaMethod(tp.resultType))
case tp => tp
}
val found1 = dropJavaMethod(found)
@@ -121,12 +121,12 @@ object ErrorReporting {
}
def typeMismatchMsg(found: Type, expected: Type, postScript: String = "") = {
- // replace constrained polyparams and their typevars by their bounds where possible
+ // replace constrained TypeParamRefs and their typevars by their bounds where possible
object reported extends TypeMap {
def setVariance(v: Int) = variance = v
val constraint = ctx.typerState.constraint
def apply(tp: Type): Type = tp match {
- case tp: PolyParam =>
+ case tp: TypeParamRef =>
constraint.entry(tp) match {
case bounds: TypeBounds =>
if (variance < 0) apply(constraint.fullUpperBound(tp))
diff --git a/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala b/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala
index 57c1808c9..5aee0fd54 100644
--- a/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala
+++ b/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala
@@ -60,7 +60,7 @@ object EtaExpansion {
def liftArgs(defs: mutable.ListBuffer[Tree], methRef: Type, args: List[Tree])(implicit ctx: Context) =
methRef.widen match {
case mt: MethodType =>
- (args, mt.paramNames, mt.paramTypes).zipped map { (arg, name, tp) =>
+ (args, mt.paramNames, mt.paramInfos).zipped map { (arg, name, tp) =>
if (tp.isInstanceOf[ExprType]) arg
else liftArg(defs, arg, if (name contains '$') "" else name.toString + "$")
}
@@ -135,12 +135,12 @@ object EtaExpansion {
val defs = new mutable.ListBuffer[tpd.Tree]
val lifted: Tree = TypedSplice(liftApp(defs, tree))
val paramTypes: List[Tree] =
- if (mt.paramTypes.length == xarity) mt.paramTypes map (_ => TypeTree())
- else mt.paramTypes map TypeTree
+ if (mt.paramInfos.length == xarity) mt.paramInfos map (_ => TypeTree())
+ else mt.paramInfos map TypeTree
val params = (mt.paramNames, paramTypes).zipped.map((name, tpe) =>
ValDef(name, tpe, EmptyTree).withFlags(Synthetic | Param).withPos(tree.pos))
var ids: List[Tree] = mt.paramNames map (name => Ident(name).withPos(tree.pos))
- if (mt.paramTypes.nonEmpty && mt.paramTypes.last.isRepeatedParam)
+ if (mt.paramInfos.nonEmpty && mt.paramInfos.last.isRepeatedParam)
ids = ids.init :+ repeated(ids.last)
var body: Tree = Apply(lifted, ids)
mt.resultType match {
diff --git a/compiler/src/dotty/tools/dotc/typer/Implicits.scala b/compiler/src/dotty/tools/dotc/typer/Implicits.scala
index 681045cc4..6c0be51df 100644
--- a/compiler/src/dotty/tools/dotc/typer/Implicits.scala
+++ b/compiler/src/dotty/tools/dotc/typer/Implicits.scala
@@ -66,16 +66,16 @@ object Implicits {
def discardForView(tpw: Type, argType: Type): Boolean = tpw match {
case mt: MethodType =>
mt.isImplicit ||
- mt.paramTypes.length != 1 ||
- !(argType relaxed_<:< mt.paramTypes.head)(ctx.fresh.setExploreTyperState)
+ mt.paramInfos.length != 1 ||
+ !(argType relaxed_<:< mt.paramInfos.head)(ctx.fresh.setExploreTyperState)
case poly: PolyType =>
// We do not need to call ProtoTypes#constrained on `poly` because
// `refMatches` is always called with mode TypevarsMissContext enabled.
poly.resultType match {
case mt: MethodType =>
mt.isImplicit ||
- mt.paramTypes.length != 1 ||
- !(argType relaxed_<:< wildApprox(mt.paramTypes.head, null, Set.empty)(ctx.fresh.setExploreTyperState))
+ mt.paramInfos.length != 1 ||
+ !(argType relaxed_<:< wildApprox(mt.paramInfos.head, null, Set.empty)(ctx.fresh.setExploreTyperState))
case rtp =>
discardForView(wildApprox(rtp, null, Set.empty), argType)
}
@@ -107,9 +107,8 @@ object Implicits {
!(isFunctionInS2 || isImplicitConverter || isConforms)
}
- def discardForValueType(tpw: Type): Boolean = tpw match {
- case mt: MethodType => !mt.isImplicit
- case mt: PolyType => discardForValueType(tpw.resultType)
+ def discardForValueType(tpw: Type): Boolean = tpw.stripPoly match {
+ case tpw: MethodType => !tpw.isImplicit
case _ => false
}
@@ -387,7 +386,7 @@ trait ImplicitRunInfo { self: RunInfo =>
case _ => arg
}
(apply(tp.tycon) /: tp.args)((tc, arg) => AndType.make(tc, applyArg(arg)))
- case tp: PolyType =>
+ case tp: TypeLambda =>
apply(tp.resType)
case _ =>
mapOver(tp)
diff --git a/compiler/src/dotty/tools/dotc/typer/Inferencing.scala b/compiler/src/dotty/tools/dotc/typer/Inferencing.scala
index 86649d78e..632dbff76 100644
--- a/compiler/src/dotty/tools/dotc/typer/Inferencing.scala
+++ b/compiler/src/dotty/tools/dotc/typer/Inferencing.scala
@@ -119,11 +119,11 @@ object Inferencing {
}
}
- /** If `tree` has a PolyType, infer its type parameters by comparing with expected type `pt` */
+ /** If `tree` has a type lambda type, infer its type parameters by comparing with expected type `pt` */
def inferTypeParams(tree: Tree, pt: Type)(implicit ctx: Context): Tree = tree.tpe match {
- case poly: PolyType =>
- val (poly1, tvars) = constrained(poly, tree)
- val tree1 = tree.withType(poly1).appliedToTypeTrees(tvars)
+ case tl: TypeLambda =>
+ val (tl1, tvars) = constrained(tl, tree)
+ val tree1 = tree.withType(tl1).appliedToTypeTrees(tvars)
tree1.tpe <:< pt
fullyDefinedType(tree1.tpe, "template parent", tree.pos)
tree1
@@ -157,7 +157,7 @@ object Inferencing {
case Apply(fn, _) =>
fn.tpe.widen match {
case mtp: MethodType =>
- val (occ, nocc) = toTest.partition(tvar => mtp.paramTypes.exists(tvar.occursIn))
+ val (occ, nocc) = toTest.partition(tvar => mtp.paramInfos.exists(tvar.occursIn))
occurring(fn, nocc, occ ::: acc)
case _ =>
occurring(fn, toTest, acc)
@@ -176,9 +176,9 @@ object Inferencing {
* -1 (minimize) if constraint is uniformly from below,
* 0 if unconstrained, or constraint is from below and above.
*/
- private def instDirection(param: PolyParam)(implicit ctx: Context): Int = {
+ private def instDirection(param: TypeParamRef)(implicit ctx: Context): Int = {
val constrained = ctx.typerState.constraint.fullBounds(param)
- val original = param.binder.paramBounds(param.paramNum)
+ val original = param.binder.paramInfos(param.paramNum)
val cmp = ctx.typeComparer
val approxBelow =
if (!cmp.isSubTypeWhenFrozen(constrained.lo, original.lo)) 1 else 0
diff --git a/compiler/src/dotty/tools/dotc/typer/Inliner.scala b/compiler/src/dotty/tools/dotc/typer/Inliner.scala
index 6e90367c8..f6d65fbb9 100644
--- a/compiler/src/dotty/tools/dotc/typer/Inliner.scala
+++ b/compiler/src/dotty/tools/dotc/typer/Inliner.scala
@@ -108,7 +108,7 @@ object Inliner {
// Add qualifier type as leading method argument to argument `tp`
def addQualType(tp: Type): Type = tp match {
- case tp: PolyType => tp.derivedPolyType(tp.paramNames, tp.paramBounds, addQualType(tp.resultType))
+ case tp: PolyType => tp.derivedLambdaType(tp.paramNames, tp.paramInfos, addQualType(tp.resultType))
case tp: ExprType => addQualType(tp.resultType)
case tp => MethodType(qualType :: Nil, tp)
}
@@ -120,7 +120,8 @@ object Inliner {
// Abstract accessed type over local refs
def abstractQualType(mtpe: Type): Type =
if (localRefs.isEmpty) mtpe
- else mtpe.LambdaAbstract(localRefs.map(_.symbol)).asInstanceOf[PolyType].flatten
+ else PolyType.fromParams(localRefs.map(_.symbol.asType), mtpe)
+ .asInstanceOf[PolyType].flatten
val accessorType = abstractQualType(addQualType(dealiasMap(accessedType)))
val accessor = accessorSymbol(tree, accessorType).asTerm
@@ -327,7 +328,7 @@ class Inliner(call: tpd.Tree, rhs: tpd.Tree)(implicit ctx: Context) {
}
computeParamBindings(tp.resultType, Nil, argss)
case tp: MethodType =>
- (tp.paramNames, tp.paramTypes, argss.head).zipped.foreach { (name, paramtp, arg) =>
+ (tp.paramNames, tp.paramInfos, argss.head).zipped.foreach { (name, paramtp, arg) =>
def isByName = paramtp.dealias.isInstanceOf[ExprType]
paramBinding(name) = arg.tpe.stripAnnots.stripTypeVar match {
case argtpe: SingletonType if isIdempotentExpr(arg) => argtpe
@@ -358,7 +359,7 @@ class Inliner(call: tpd.Tree, rhs: tpd.Tree)(implicit ctx: Context) {
* 2. If given type refers to a parameter, make `paramProxy` refer to the entry stored
* in `paramNames` under the parameter's name. This roundabout way to bind parameter
* references to proxies is done because we not known a priori what the parameter
- * references of a method are (we only know the method's type, but that contains PolyParams
+ * references of a method are (we only know the method's type, but that contains TypeParamRefs
* and MethodParams, not TypeRefs or TermRefs.
*/
private def registerType(tpe: Type): Unit = tpe match {
diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala
index 94506f318..ce2030c01 100644
--- a/compiler/src/dotty/tools/dotc/typer/Namer.scala
+++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala
@@ -113,9 +113,9 @@ trait NamerContextOps { this: Context =>
if (isJava)
for (param <- params)
if (param.info.isDirectRef(defn.ObjectClass)) param.info = defn.AnyType
- make.fromSymbols(params, resultType)
+ make.fromSymbols(params.asInstanceOf[List[TermSymbol]], resultType)
}
- if (typeParams.nonEmpty) monotpe.LambdaAbstract(typeParams)
+ if (typeParams.nonEmpty) PolyType.fromParams(typeParams.asInstanceOf[List[TypeSymbol]], monotpe)
else if (valueParamss.isEmpty) ExprType(monotpe)
else monotpe
}
@@ -298,7 +298,7 @@ class Namer { typer: Typer =>
val inSuperCall1 = if (tree.mods is ParamOrAccessor) EmptyFlags else inSuperCall
// suppress inSuperCall for constructor parameters
val higherKinded = tree match {
- case TypeDef(_, PolyTypeTree(_, _)) if isDeferred => HigherKinded
+ case TypeDef(_, LambdaTypeTree(_, _)) if isDeferred => HigherKinded
case _ => EmptyFlags
}
@@ -564,7 +564,6 @@ class Namer { typer: Typer =>
case _ =>
}
case _ =>
-
}
}
@@ -796,7 +795,7 @@ class Namer { typer: Typer =>
myTypeParams = {
implicit val ctx = nestedCtx
val tparams = original.rhs match {
- case PolyTypeTree(tparams, _) => tparams
+ case LambdaTypeTree(tparams, _) => tparams
case _ => Nil
}
completeParams(tparams)
@@ -1033,7 +1032,7 @@ class Namer { typer: Typer =>
}
val defaultAlts = meth.altsWith(_.hasDefaultParams)
if (defaultAlts.length == 1)
- paramProto(defaultAlts.head.info.widen.paramTypess, idx)
+ paramProto(defaultAlts.head.info.widen.paramInfoss, idx)
else
WildcardType
}
@@ -1152,9 +1151,7 @@ class Namer { typer: Typer =>
}
def typeDefSig(tdef: TypeDef, sym: Symbol, tparamSyms: List[TypeSymbol])(implicit ctx: Context): Type = {
- def abstracted(tp: Type): Type =
- if (tparamSyms.nonEmpty) tp.LambdaAbstract(tparamSyms) else tp
-
+ def abstracted(tp: Type): Type = HKTypeLambda.fromParams(tparamSyms, tp)
val dummyInfo = abstracted(TypeBounds.empty)
sym.info = dummyInfo
// Temporarily set info of defined type T to ` >: Nothing <: Any.
@@ -1170,7 +1167,7 @@ class Namer { typer: Typer =>
val isDerived = tdef.rhs.isInstanceOf[untpd.DerivedTypeTree]
val rhs = tdef.rhs match {
- case PolyTypeTree(_, body) => body
+ case LambdaTypeTree(_, body) => body
case rhs => rhs
}
val rhsBodyType = typedAheadType(rhs).tpe
diff --git a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala
index f7dd725c8..ab342dc17 100644
--- a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala
+++ b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala
@@ -192,7 +192,7 @@ object ProtoTypes {
/** Forget the types of any arguments that have been typed producing a constraint in a
* typer state that is not yet committed into the one of the current context `ctx`.
- * This is necessary to avoid "orphan" PolyParams that are referred to from
+ * This is necessary to avoid "orphan" TypeParamRefs that are referred to from
* type variables in the typed arguments, but that are not registered in the
* current constraint. A test case is pos/t1756.scala.
* @return True if all arguments have types (in particular, no types were forgotten).
@@ -369,53 +369,53 @@ object ProtoTypes {
/** A prototype for type constructors that are followed by a type application */
@sharable object AnyTypeConstructorProto extends UncachedGroundType with MatchAlways
- /** Add all parameters in given polytype `pt` to the constraint's domain.
+ /** Add all parameters of given type lambda `tl` to the constraint's domain.
* If the constraint contains already some of these parameters in its domain,
- * make a copy of the polytype and add the copy's type parameters instead.
- * Return either the original polytype, or the copy, if one was made.
+ * make a copy of the type lambda and add the copy's type parameters instead.
+ * Return either the original type lambda, or the copy, if one was made.
* Also, if `owningTree` is non-empty, add a type variable for each parameter.
- * @return The added polytype, and the list of created type variables.
+ * @return The added type lambda, and the list of created type variables.
*/
- def constrained(pt: PolyType, owningTree: untpd.Tree)(implicit ctx: Context): (PolyType, List[TypeTree]) = {
+ def constrained(tl: TypeLambda, owningTree: untpd.Tree)(implicit ctx: Context): (TypeLambda, List[TypeTree]) = {
val state = ctx.typerState
assert(!(ctx.typerState.isCommittable && owningTree.isEmpty),
s"inconsistent: no typevars were added to committable constraint ${state.constraint}")
- def newTypeVars(pt: PolyType): List[TypeTree] =
- for (n <- (0 until pt.paramNames.length).toList)
+ def newTypeVars(tl: TypeLambda): List[TypeTree] =
+ for (n <- (0 until tl.paramNames.length).toList)
yield {
val tt = new TypeTree().withPos(owningTree.pos)
- tt.withType(new TypeVar(PolyParam(pt, n), state, tt, ctx.owner))
+ tt.withType(new TypeVar(TypeParamRef(tl, n), state, tt, ctx.owner))
}
val added =
- if (state.constraint contains pt) pt.newLikeThis(pt.paramNames, pt.paramBounds, pt.resultType)
- else pt
+ if (state.constraint contains tl) tl.newLikeThis(tl.paramNames, tl.paramInfos, tl.resultType)
+ else tl
val tvars = if (owningTree.isEmpty) Nil else newTypeVars(added)
ctx.typeComparer.addToConstraint(added, tvars.tpes.asInstanceOf[List[TypeVar]])
(added, tvars)
}
- /** Same as `constrained(pt, EmptyTree)`, but returns just the created polytype */
- def constrained(pt: PolyType)(implicit ctx: Context): PolyType = constrained(pt, EmptyTree)._1
+ /** Same as `constrained(tl, EmptyTree)`, but returns just the created type lambda */
+ def constrained(tl: TypeLambda)(implicit ctx: Context): TypeLambda = constrained(tl, 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)(
+ /** Create a new TypeParamRef that represents a dependent method parameter singleton */
+ def newDepTypeParamRef(tp: Type)(implicit ctx: Context): TypeParamRef = {
+ val poly = PolyType(ctx.freshName(nme.DEP_PARAM_PREFIX).toTypeName :: Nil)(
pt => TypeBounds.upper(AndType(tp, defn.SingletonType)) :: Nil,
pt => defn.AnyType)
ctx.typeComparer.addToConstraint(poly, Nil)
- PolyParam(poly, 0)
+ TypeParamRef(poly, 0)
}
/** The result type of `mt`, where all references to parameters of `mt` are
- * replaced by either wildcards (if typevarsMissContext) or polyparams.
+ * replaced by either wildcards (if typevarsMissContext) or TypeParamRefs.
*/
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))
+ if (ctx.mode.is(Mode.TypevarsMissContext)) WildcardType else newDepTypeParamRef(tp)
+ mt.resultType.substParams(mt, mt.paramInfos.map(replacement))
}
else mt.resultType
@@ -444,10 +444,10 @@ object ProtoTypes {
val rt = normalize(mt.resultType, pt)
pt match {
case pt: IgnoredProto => mt
- case pt: ApplyingProto => mt.derivedMethodType(mt.paramNames, mt.paramTypes, rt)
+ case pt: ApplyingProto => mt.derivedLambdaType(mt.paramNames, mt.paramInfos, rt)
case _ =>
- val ft = defn.FunctionOf(mt.paramTypes, rt)
- if (mt.paramTypes.nonEmpty || ft <:< pt) ft else rt
+ val ft = defn.FunctionOf(mt.paramInfos, rt)
+ if (mt.paramInfos.nonEmpty || ft <:< pt) ft else rt
}
}
case et: ExprType => et.resultType
@@ -458,7 +458,7 @@ object ProtoTypes {
/** Approximate occurrences of parameter types and uninstantiated typevars
* by wildcard types.
*/
- final def wildApprox(tp: Type, theMap: WildApproxMap, seen: Set[PolyParam])(implicit ctx: Context): Type = tp match {
+ final def wildApprox(tp: Type, theMap: WildApproxMap, seen: Set[TypeParamRef])(implicit ctx: Context): Type = tp match {
case tp: NamedType => // default case, inlined for speed
if (tp.symbol.isStatic) tp
else tp.derivedSelect(wildApprox(tp.prefix, theMap, seen))
@@ -469,13 +469,13 @@ object ProtoTypes {
wildApprox(tp.refinedInfo, theMap, seen))
case tp: TypeAlias => // default case, inlined for speed
tp.derivedTypeAlias(wildApprox(tp.alias, theMap, seen))
- case tp @ PolyParam(poly, pnum) =>
+ case tp @ TypeParamRef(poly, pnum) =>
def wildApproxBounds(bounds: TypeBounds) =
if (bounds.lo.isInstanceOf[NamedType] && bounds.hi.isInstanceOf[NamedType])
WildcardType(wildApprox(bounds, theMap, seen).bounds)
else if (seen.contains(tp)) WildcardType
else WildcardType(wildApprox(bounds, theMap, seen + tp).bounds)
- def unconstrainedApprox = wildApproxBounds(poly.paramBounds(pnum))
+ def unconstrainedApprox = wildApproxBounds(poly.paramInfos(pnum))
def approxPoly =
if (ctx.mode.is(Mode.TypevarsMissContext)) unconstrainedApprox
else
@@ -485,8 +485,8 @@ object ProtoTypes {
case inst => wildApprox(inst, theMap, seen)
}
approxPoly
- case MethodParam(mt, pnum) =>
- WildcardType(TypeBounds.upper(wildApprox(mt.paramTypes(pnum), theMap, seen)))
+ case TermParamRef(mt, pnum) =>
+ WildcardType(TypeBounds.upper(wildApprox(mt.paramInfos(pnum), theMap, seen)))
case tp: TypeVar =>
wildApprox(tp.underlying, theMap, seen)
case tp @ HKApply(tycon, args) =>
@@ -532,14 +532,14 @@ object ProtoTypes {
@sharable object AssignProto extends UncachedGroundType with MatchAlways
- private[ProtoTypes] class WildApproxMap(val seen: Set[PolyParam])(implicit ctx: Context) extends TypeMap {
+ private[ProtoTypes] class WildApproxMap(val seen: Set[TypeParamRef])(implicit ctx: Context) extends TypeMap {
def apply(tp: Type) = wildApprox(tp, this, seen)
}
/** Dummy tree to be used as an argument of a FunProto or ViewProto type */
object dummyTreeOfType {
def apply(tp: Type): Tree = untpd.Literal(Constant(null)) withTypeUnchecked tp
- def unapply(tree: Tree): Option[Type] = tree match {
+ def unapply(tree: untpd.Tree): Option[Type] = tree match {
case Literal(Constant(null)) => Some(tree.typeOpt)
case _ => None
}
diff --git a/compiler/src/dotty/tools/dotc/typer/ReTyper.scala b/compiler/src/dotty/tools/dotc/typer/ReTyper.scala
index 6080c6644..73e676b57 100644
--- a/compiler/src/dotty/tools/dotc/typer/ReTyper.scala
+++ b/compiler/src/dotty/tools/dotc/typer/ReTyper.scala
@@ -86,7 +86,7 @@ class ReTyper extends Typer {
override def handleUnexpectedFunType(tree: untpd.Apply, fun: Tree)(implicit ctx: Context): Tree = fun.tpe match {
case mt: MethodType =>
- val args: List[Tree] = tree.args.zipWithConserve(mt.paramTypes)(typedExpr(_, _)).asInstanceOf[List[Tree]]
+ val args: List[Tree] = tree.args.zipWithConserve(mt.paramInfos)(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/TypeAssigner.scala b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala
index 6d0fc08f9..2aa7036b4 100644
--- a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala
+++ b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala
@@ -106,7 +106,7 @@ trait TypeAssigner {
val base = apply(tycon)
var args = tp.baseArgInfos(base.typeSymbol)
if (base.typeParams.length != args.length)
- args = base.typeParams.map(_.paramBounds)
+ args = base.typeParams.map(_.paramInfo)
apply(base.appliedTo(args))
case tp @ RefinedType(parent, name, rinfo) if variance > 0 =>
val parent1 = apply(tp.parent)
@@ -318,9 +318,9 @@ trait TypeAssigner {
def assignType(tree: untpd.Apply, fn: Tree, args: List[Tree])(implicit ctx: Context) = {
val ownType = fn.tpe.widen match {
case fntpe: MethodType =>
- if (sameLength(fntpe.paramTypes, args) || ctx.phase.prev.relaxedTyping) fntpe.instantiate(args.tpes)
+ if (sameLength(fntpe.paramInfos, args) || ctx.phase.prev.relaxedTyping) fntpe.instantiate(args.tpes)
else
- errorType(i"wrong number of arguments for $fntpe: ${fn.tpe}, expected: ${fntpe.paramTypes.length}, found: ${args.length}", tree.pos)
+ errorType(i"wrong number of arguments for $fntpe: ${fn.tpe}, expected: ${fntpe.paramInfos.length}, found: ${args.length}", tree.pos)
case t =>
errorType(i"${err.exprStr(fn)} does not take parameters", tree.pos)
}
@@ -329,7 +329,7 @@ trait TypeAssigner {
def assignType(tree: untpd.TypeApply, fn: Tree, args: List[Tree])(implicit ctx: Context) = {
val ownType = fn.tpe.widen match {
- case pt: PolyType =>
+ case pt: TypeLambda =>
val paramNames = pt.paramNames
if (hasNamedArg(args)) {
// Type arguments which are specified by name (immutable after this first loop)
@@ -348,7 +348,7 @@ trait TypeAssigner {
val newIndex = gapBuf.length
gapBuf += idx
// Re-index unassigned type arguments that remain after transformation
- PolyParam(pt, newIndex)
+ TypeParamRef(pt, newIndex)
}
// Type parameters after naming assignment, conserving paramNames order
@@ -358,7 +358,7 @@ trait TypeAssigner {
val transform = new TypeMap {
def apply(t: Type) = t match {
- case PolyParam(`pt`, idx) => normArgs(idx)
+ case TypeParamRef(`pt`, idx) => normArgs(idx)
case _ => mapOver(t)
}
}
@@ -366,9 +366,9 @@ trait TypeAssigner {
if (gapBuf.isEmpty) resultType1
else {
val gaps = gapBuf.toList
- pt.derivedPolyType(
+ pt.derivedLambdaType(
gaps.map(paramNames),
- gaps.map(idx => transform(pt.paramBounds(idx)).bounds),
+ gaps.map(idx => transform(pt.paramInfos(idx)).bounds),
resultType1)
}
}
@@ -459,8 +459,8 @@ trait TypeAssigner {
tree.withType(ownType)
}
- def assignType(tree: untpd.PolyTypeTree, tparamDefs: List[TypeDef], body: Tree)(implicit ctx: Context) =
- tree.withType(body.tpe.LambdaAbstract(tparamDefs.map(_.symbol)))
+ def assignType(tree: untpd.LambdaTypeTree, tparamDefs: List[TypeDef], body: Tree)(implicit ctx: Context) =
+ tree.withType(HKTypeLambda.fromParams(tparamDefs.map(_.symbol.asType), body.tpe))
def assignType(tree: untpd.ByNameTypeTree, result: Tree)(implicit ctx: Context) =
tree.withType(ExprType(result.tpe))
diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala
index d4a9744e4..2760ceba9 100644
--- a/compiler/src/dotty/tools/dotc/typer/Typer.scala
+++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala
@@ -741,14 +741,14 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
calleeType.widen match {
case mtpe: MethodType =>
val pos = params indexWhere (_.name == param.name)
- if (pos < mtpe.paramTypes.length) {
- val ptype = mtpe.paramTypes(pos)
+ if (pos < mtpe.paramInfos.length) {
+ val ptype = mtpe.paramInfos(pos)
if (isFullyDefined(ptype, ForceDegree.noBottom)) return ptype
}
case _ =>
}
val ofFun =
- if (nme.syntheticParamNames(args.length + 1) contains param.name)
+ if (MethodType.syntheticParamNames(args.length + 1) contains param.name)
i" of expanded function $tree"
else
""
@@ -1074,10 +1074,10 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
wrongNumberOfTypeArgs(tpt1.tpe, tparams, args, tree.pos)
args = args.take(tparams.length)
}
- def typedArg(arg: untpd.Tree, tparam: TypeParamInfo) = {
+ def typedArg(arg: untpd.Tree, tparam: ParamInfo) = {
val (desugaredArg, argPt) =
if (ctx.mode is Mode.Pattern)
- (if (isVarPattern(arg)) desugar.patternVar(arg) else arg, tparam.paramBounds)
+ (if (isVarPattern(arg)) desugar.patternVar(arg) else arg, tparam.paramInfo)
else
(arg, WildcardType)
if (tpt1.symbol.isClass)
@@ -1096,12 +1096,12 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
}
}
- def typedPolyTypeTree(tree: untpd.PolyTypeTree)(implicit ctx: Context): Tree = track("typedPolyTypeTree") {
- val PolyTypeTree(tparams, body) = tree
+ def typedLambdaTypeTree(tree: untpd.LambdaTypeTree)(implicit ctx: Context): Tree = track("typedLambdaTypeTree") {
+ val LambdaTypeTree(tparams, body) = tree
indexAndAnnotate(tparams)
val tparams1 = tparams.mapconserve(typed(_).asInstanceOf[TypeDef])
val body1 = typedType(tree.body)
- assignType(cpy.PolyTypeTree(tree)(tparams1, body1), tparams1, body1)
+ assignType(cpy.LambdaTypeTree(tree)(tparams1, body1), tparams1, body1)
}
def typedByNameTypeTree(tree: untpd.ByNameTypeTree)(implicit ctx: Context): ByNameTypeTree = track("typedByNameTypeTree") {
@@ -1262,10 +1262,10 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
val TypeDef(name, rhs) = tdef
completeAnnotations(tdef, sym)
val rhs1 = tdef.rhs match {
- case rhs @ PolyTypeTree(tparams, body) =>
+ case rhs @ LambdaTypeTree(tparams, body) =>
val tparams1 = tparams.map(typed(_)).asInstanceOf[List[TypeDef]]
val body1 = typedType(body)
- assignType(cpy.PolyTypeTree(rhs)(tparams1, body1), tparams1, body1)
+ assignType(cpy.LambdaTypeTree(rhs)(tparams1, body1), tparams1, body1)
case rhs =>
typedType(rhs)
}
@@ -1285,9 +1285,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
* @param psym Its type symbol
* @param cinfo The info of its constructor
*/
- def maybeCall(ref: Tree, psym: Symbol, cinfo: Type): Tree = cinfo match {
- case cinfo: PolyType =>
- maybeCall(ref, psym, cinfo.resultType)
+ def maybeCall(ref: Tree, psym: Symbol, cinfo: Type): Tree = cinfo.stripPoly match {
case cinfo @ MethodType(Nil) if cinfo.resultType.isInstanceOf[ImplicitMethodType] =>
val icall = New(ref).select(nme.CONSTRUCTOR).appliedToNone
typedExpr(untpd.TypedSplice(icall))(superCtx)
@@ -1555,7 +1553,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
case tree: untpd.OrTypeTree => typedOrTypeTree(tree)
case tree: untpd.RefinedTypeTree => typedRefinedTypeTree(tree)
case tree: untpd.AppliedTypeTree => typedAppliedTypeTree(tree)
- case tree: untpd.PolyTypeTree => typedPolyTypeTree(tree)(localContext(tree, NoSymbol).setNewScope)
+ case tree: untpd.LambdaTypeTree => typedLambdaTypeTree(tree)(localContext(tree, NoSymbol).setNewScope)
case tree: untpd.ByNameTypeTree => typedByNameTypeTree(tree)
case tree: untpd.TypeBoundsTree => typedTypeBoundsTree(tree)
case tree: untpd.Alternative => typedAlternative(tree, pt)
@@ -1741,7 +1739,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
def adapt(tree: Tree, pt: Type, original: untpd.Tree = untpd.EmptyTree)(implicit ctx: Context): Tree = /*>|>*/ track("adapt") /*<|<*/ {
/*>|>*/ ctx.traceIndented(i"adapting $tree of type ${tree.tpe} to $pt", typr, show = true) /*<|<*/ {
if (tree.isDef) interpolateUndetVars(tree, tree.symbol)
- else if (!tree.tpe.widen.isInstanceOf[MethodOrPoly]) interpolateUndetVars(tree, NoSymbol)
+ else if (!tree.tpe.widen.isInstanceOf[LambdaType]) interpolateUndetVars(tree, NoSymbol)
tree.overwriteType(tree.tpe.simplified)
adaptInterpolated(tree, pt, original)
}
@@ -1809,12 +1807,12 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
errorTree(tree,
em"""none of the ${err.overloadedAltsStr(altDenots)}
|match $expectedStr""")
- def hasEmptyParams(denot: SingleDenotation) = denot.info.paramTypess == ListOfNil
+ def hasEmptyParams(denot: SingleDenotation) = denot.info.paramInfoss == ListOfNil
pt match {
case pt: FunProto =>
tryInsertApplyOrImplicit(tree, pt)(noMatches)
case _ =>
- if (altDenots exists (_.info.paramTypess == ListOfNil))
+ if (altDenots exists (_.info.paramInfoss == ListOfNil))
typed(untpd.Apply(untpd.TypedSplice(tree), Nil), pt)
else
noMatches
@@ -1841,7 +1839,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
}
def adaptToArgs(wtp: Type, pt: FunProto): Tree = wtp match {
- case _: MethodType | _: PolyType =>
+ case _: MethodOrPoly =>
if (pt.args.lengthCompare(1) > 0 && isUnary(wtp) && ctx.canAutoTuple)
adaptInterpolated(tree, pt.tupled, original)
else
@@ -1871,7 +1869,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
case TypeBounds(lo, hi)
if (lo eq hi) || (hi <:< lo)(ctx.fresh.setExploreTyperState) =>
inst(lo)
- case tp: PolyParam =>
+ case tp: TypeParamRef =>
constraint.typeVarOfParam(tp).orElse(tp)
case _ => tp
}
@@ -1886,7 +1884,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
adaptInterpolated(tree.withType(wtp.resultType), pt, original)
case wtp: ImplicitMethodType if constrainResult(wtp, followAlias(pt)) =>
val tvarsToInstantiate = tvarsInParams(tree)
- wtp.paramTypes.foreach(instantiateSelected(_, tvarsToInstantiate))
+ wtp.paramInfos.foreach(instantiateSelected(_, tvarsToInstantiate))
val constr = ctx.typerState.constraint
def addImplicitArgs(implicit ctx: Context) = {
val errors = new mutable.ListBuffer[() => String]
@@ -1898,7 +1896,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
for (err <- errors) ctx.error(err(), tree.pos.endPos)
tree.withType(wtp.resultType)
}
- val args = (wtp.paramNames, wtp.paramTypes).zipped map { (pname, formal) =>
+ val args = (wtp.paramNames, wtp.paramInfos).zipped map { (pname, formal) =>
def implicitArgError(msg: String => String) =
errors += (() => msg(em"parameter $pname of $methodStr"))
if (errors.nonEmpty) EmptyTree
@@ -1941,11 +1939,11 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
// prioritize method parameter types as parameter types of the eta-expanded closure
0
else defn.functionArity(pt)
- else if (pt eq AnyFunctionProto) wtp.paramTypes.length
+ else if (pt eq AnyFunctionProto) wtp.paramInfos.length
else -1
if (arity >= 0 && !tree.symbol.isConstructor)
typed(etaExpand(tree, wtp, arity), pt)
- else if (wtp.paramTypes.isEmpty)
+ else if (wtp.paramInfos.isEmpty)
adaptInterpolated(tpd.Apply(tree, Nil), pt, EmptyTree)
else if (wtp.isImplicit)
err.typeMismatch(tree, pt)
diff --git a/compiler/src/dotty/tools/dotc/typer/VarianceChecker.scala b/compiler/src/dotty/tools/dotc/typer/VarianceChecker.scala
index d5dd5a024..f88098519 100644
--- a/compiler/src/dotty/tools/dotc/typer/VarianceChecker.scala
+++ b/compiler/src/dotty/tools/dotc/typer/VarianceChecker.scala
@@ -88,10 +88,8 @@ class VarianceChecker()(implicit ctx: Context) {
if (sym.variance != 0 && base.isContainedIn(sym.owner)) checkVarianceOfSymbol(sym)
else if (sym.isAliasType) this(status, sym.info.bounds.hi)
else foldOver(status, tp)
- case tp: MethodType =>
- this(status, tp.resultType) // params will be checked in their TypeDef nodes.
- case tp: PolyType =>
- this(status, tp.resultType) // params will be checked in their ValDef nodes.
+ case tp: MethodOrPoly =>
+ this(status, tp.resultType) // params will be checked in their TypeDef or ValDef nodes.
case AnnotatedType(_, annot) if annot.symbol == defn.UncheckedVarianceAnnot =>
status
//case tp: ClassInfo =>
diff --git a/compiler/src/dotty/tools/dotc/typer/Variances.scala b/compiler/src/dotty/tools/dotc/typer/Variances.scala
index 5a1745930..aeeef0275 100644
--- a/compiler/src/dotty/tools/dotc/typer/Variances.scala
+++ b/compiler/src/dotty/tools/dotc/typer/Variances.scala
@@ -79,12 +79,12 @@ object Variances {
varianceInType(parent)(tparam) & varianceInType(rinfo)(tparam)
case tp: RecType =>
varianceInType(tp.parent)(tparam)
- case tp: MethodType =>
- flip(varianceInTypes(tp.paramTypes)(tparam)) & varianceInType(tp.resultType)(tparam)
+ case tp: MethodOrPoly =>
+ flip(varianceInTypes(tp.paramInfos)(tparam)) & varianceInType(tp.resultType)(tparam)
case ExprType(restpe) =>
varianceInType(restpe)(tparam)
case tp @ HKApply(tycon, args) =>
- def varianceInArgs(v: Variance, args: List[Type], tparams: List[TypeParamInfo]): Variance =
+ def varianceInArgs(v: Variance, args: List[Type], tparams: List[ParamInfo]): Variance =
args match {
case arg :: args1 =>
varianceInArgs(
@@ -94,8 +94,6 @@ object Variances {
v
}
varianceInArgs(varianceInType(tycon)(tparam), args, tycon.typeParams)
- case tp: PolyType =>
- flip(varianceInTypes(tp.paramBounds)(tparam)) & varianceInType(tp.resultType)(tparam)
case AnnotatedType(tp, annot) =>
varianceInType(tp)(tparam) & varianceInAnnot(annot)(tparam)
case tp: AndOrType =>
diff --git a/compiler/test/dotty/tools/dotc/parsing/DocstringTests.scala b/compiler/test/dotty/tools/dotc/parsing/DocstringTests.scala
index 930ec117a..81ac77761 100644
--- a/compiler/test/dotty/tools/dotc/parsing/DocstringTests.scala
+++ b/compiler/test/dotty/tools/dotc/parsing/DocstringTests.scala
@@ -488,4 +488,34 @@ class DocstringTests extends DocstringTest {
checkDocString(c.rawComment.map(_.raw), "/** Class1 */")
}
}
+
+ @Test def nestedComment = {
+ val source =
+ """
+ |trait T {
+ | /** Cheeky comment */
+ |}
+ |class C
+ """.stripMargin
+
+ import dotty.tools.dotc.ast.untpd._
+ checkFrontend(source) {
+ case p @ PackageDef(_, Seq(_, c: TypeDef)) =>
+ assert(c.rawComment == None, s"class C is not supposed to have a docstring (${c.rawComment.get}) in:$source")
+ }
+ }
+
+ @Test def eofComment = {
+ val source =
+ """
+ |class C
+ |/** Cheeky comment */
+ """.stripMargin
+
+ import dotty.tools.dotc.ast.untpd._
+ checkFrontend(source) {
+ case p @ PackageDef(_, Seq(c: TypeDef)) =>
+ assert(c.rawComment == None, s"class C is not supposed to have a docstring (${c.rawComment.get}) in:$source")
+ }
+ }
} /* End class */
diff --git a/compiler/test/dotty/tools/dotc/repl/TestREPL.scala b/compiler/test/dotty/tools/dotc/repl/TestREPL.scala
index 131a88ab1..c5557b86e 100644
--- a/compiler/test/dotty/tools/dotc/repl/TestREPL.scala
+++ b/compiler/test/dotty/tools/dotc/repl/TestREPL.scala
@@ -4,7 +4,7 @@ package repl
import core.Contexts.Context
import collection.mutable
-import java.io.StringWriter
+import java.io.{StringWriter, PrintStream}
import dotty.tools.io.{ PlainFile, Directory }
import org.junit.Test
@@ -58,8 +58,11 @@ class TestREPL(script: String) extends REPL {
val printed = out.toString
val transcript = printed.drop(printed.indexOf(config.prompt))
if (transcript.toString.lines.toList != script.lines.toList) {
- println("input differs from transcript:")
+ println("input differs from transcript (copy is repl.transcript):")
println(transcript)
+ val s = new PrintStream("repl.transcript")
+ s.print(transcript)
+ s.close()
assert(false)
}
}
diff --git a/doc-tool/resources/_layouts/main.html b/doc-tool/resources/_layouts/main.html
index 7c63ec610..eb0dd51fd 100644
--- a/doc-tool/resources/_layouts/main.html
+++ b/doc-tool/resources/_layouts/main.html
@@ -13,6 +13,7 @@
integrity="sha384-AysaV+vQoT3kOAXZkl02PThvDr8HYKPZhNT5h/CXfBThSRXQ6jW5DO2ekP5ViFdi"
crossorigin="anonymous"
>
+
<link
rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css"
diff --git a/doc-tool/resources/_layouts/sidebar.html b/doc-tool/resources/_layouts/sidebar.html
index b3947c884..24ed1bed7 100644
--- a/doc-tool/resources/_layouts/sidebar.html
+++ b/doc-tool/resources/_layouts/sidebar.html
@@ -33,9 +33,12 @@ layout: main
</ul>
</div>
<div id="content-body">
- <div id="menu-toggle" onclick="toggleMenu()">
- <i class="fa fa-bars" aria-hidden="true"></i>
- </div>
+ <button type="button" id="menu-toggle" onclick="toggleMenu()" aria-expanded="false">
+ <span class="sr-only" aria-hidden="true">Toggle navigation</span>
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ </button>
{{ content }}
</div>
</div>
diff --git a/doc-tool/resources/css/dottydoc.css b/doc-tool/resources/css/dottydoc.css
index a89e23375..140f15eba 100644
--- a/doc-tool/resources/css/dottydoc.css
+++ b/doc-tool/resources/css/dottydoc.css
@@ -1,23 +1,31 @@
+html, body {
+ overflow-x: hidden;
+}
+
html {
height: 100%;
}
+
body {
min-height: 100%;
}
div#content-wrapper {
min-height: 100vh;
- padding-left: 250px;
- transition: all 0.5s ease;
+ padding-left: 0;
}
-div#content-wrapper.toggled {
- padding-left: 0;
+div#content-wrapper div#content-body {
+ background-color: #f4f3f4;
+ border-left: 1px solid #e0e0e0;
+ box-shadow: -3px 0 5px -2px rgba(0, 0, 0, 0.14);
+ padding: 40px 1px 1px 1px;
+ position: relative;
+ min-height: 100vh;
}
-div.index-wrapper {
+div#content-wrapper div.index-wrapper {
background-color: #fafafa;
- width: 250px;
position: fixed;
top: 0;
left: 0;
@@ -26,6 +34,77 @@ div.index-wrapper {
overflow-x: hidden;
}
+/** Animations: Easing for content body slide on toggle */
+div#content-wrapper,
+div#content-wrapper div#content-body {
+ -webkit-transition: all .25s ease-out;
+ -o-transition: all .25s ease-out;
+ transition: all .25s ease-out;
+}
+
+/** Mobile (x < 576px) sidebar: Defaults closed with 60% wide sidebar */
+div#content-wrapper {}
+div#content-wrapper div#content-body { left: 0; }
+div#content-wrapper div.index-wrapper { width: 60%; }
+
+div#content-wrapper.toggled {}
+div#content-wrapper.toggled div#content-body { left: 60%; }
+div#content-wrapper.toggled div.index-wrapper {}
+
+/** Tablet (576px <= x < 768px) sidebar: Defaults closed with 250px wide sidebar */
+@media screen and (min-width: 576px) {
+
+ div#content-wrapper {}
+ div#content-wrapper div#content-body {}
+ div#content-wrapper div.index-wrapper { width: 250px; }
+
+ div#content-wrapper.toggled {}
+ div#content-wrapper.toggled div#content-body { left: 250px; }
+ div#content-wrapper.toggled div.index-wrapper {}
+
+}
+
+/** Desktop (x >= 768px) sidebar: Defaults open with 250px wide sidebar */
+@media screen and (min-width: 768px) {
+
+ div#content-wrapper { padding-left: 250px; }
+ div#content-wrapper div#content-body {}
+ div#content-wrapper div.index-wrapper { width: 250px; }
+
+ div#content-wrapper.toggled { padding-left: 0; }
+ div#content-wrapper.toggled div#content-body { left: 0; }
+ div#content-wrapper.toggled div.index-wrapper {}
+
+}
+
+div#content-wrapper button#menu-toggle {
+ background: rgba(244, 243, 244, 0.4) none;
+ border: 1px solid transparent;
+ color: #837f84;
+ margin: -30px 0 0 10px;
+ padding: 9px 10px;
+ position: absolute;
+}
+
+div#content-wrapper button#menu-toggle:hover {
+ cursor: pointer;
+}
+
+div#content-wrapper button#menu-toggle:focus {
+ outline: none;
+}
+
+div#content-wrapper button#menu-toggle span.icon-bar {
+ background-color: #837f84;
+ border-radius: 2px;
+ border-color: #837f84;
+ color: #837f84;
+ display: block;
+ margin: 3px 0;
+ width: 15px;
+ height: 2px;
+}
+
div#doc-page-container > h1 {
border-bottom: 1px solid #eee;
padding-bottom: 0.3em;
@@ -93,27 +172,6 @@ div#doc-page-container > h6 > a:focus {
outline: none;
}
-div#content-body {
- border-left: 1px solid #e0e0e0;
- box-shadow: -3px 0px 5px -2px rgba(0,0,0,0.14);
- position: relative;
- padding: 10px;
- background-color: #f4f3f4;
- min-height: 100vh;
-}
-
-div#menu-toggle {
- color: #837F84;
- outline: none;
- padding-left: 20px;
- padding-top: 10px;
-}
-
-div#menu-toggle:hover {
- color: rgba(0, 0, 0, 0.4);
- cursor: pointer;
-}
-
ul.index-entities {
list-style-type: none;
padding-left: 0;
@@ -195,7 +253,7 @@ ul.index-entities > li > a.entity-name {
font-size: 13px;
display: block;
padding: 0 0 0 24px;
- color: rgba(0,0,0,.87);
+ color: rgba(0, 0, 0, 0.87);
background: transparent;
cursor: pointer;
float: left;
@@ -245,7 +303,7 @@ ul.toc > li > ul.hide {
ul.index-entities > li.index-title > span {
font-size: 16px;
font-weight: bold;
- color: rgba(0,0,0,.87);
+ color: rgba(0, 0, 0, 0.87);
padding: 0 24px;
}
@@ -319,7 +377,7 @@ pre {
background: rgba(244, 243, 244, 0.6);
border-radius: 2px;
margin-top: 20px;
- border: 1px solid rgba(0,0,0,0.1);
+ border: 1px solid rgba(0, 0, 0, 0.1);
}
pre > code.language-none,
diff --git a/doc-tool/src/dotty/tools/dottydoc/core/DocASTPhase.scala b/doc-tool/src/dotty/tools/dottydoc/core/DocASTPhase.scala
index cfb66fa56..ad8981ea2 100644
--- a/doc-tool/src/dotty/tools/dottydoc/core/DocASTPhase.scala
+++ b/doc-tool/src/dotty/tools/dottydoc/core/DocASTPhase.scala
@@ -94,10 +94,7 @@ class DocASTPhase extends Phase {
NonEntity
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 tp: PolyType => tp.paramNames.map(_.show)
case _ => Nil
}
TypeAliasImpl(sym, annotations(sym), flags(t), t.name.show.split("\\$\\$").last, path(sym), alias(t.rhs.tpe), tparams)
diff --git a/doc-tool/src/dotty/tools/dottydoc/model/factories.scala b/doc-tool/src/dotty/tools/dottydoc/model/factories.scala
index 3e766a990..03f11335e 100644
--- a/doc-tool/src/dotty/tools/dottydoc/model/factories.scala
+++ b/doc-tool/src/dotty/tools/dottydoc/model/factories.scala
@@ -79,7 +79,7 @@ object factories {
case TypeBounds(lo, hi) =>
BoundsReference(expandTpe(lo), expandTpe(hi))
- case t: PolyParam =>
+ case t: TypeParamRef =>
typeRef(t.paramName.show, params = params)
case ExprType(tpe) =>
@@ -106,7 +106,7 @@ object factories {
case ci: ClassInfo =>
typeRef(ci.cls.name.show, query = ci.typeSymbol.showFullName)
- case tl: PolyType =>
+ case tl: TypeLambda =>
expandTpe(tl.resType)
case OrType(left, right) =>
@@ -127,7 +127,7 @@ object factories {
def typeParams(sym: Symbol)(implicit ctx: Context): List[String] =
sym.info match {
- case pt: PolyType => // TODO: not sure if this case is needed anymore
+ case pt: TypeLambda => // TODO: not sure if this case is needed anymore
pt.paramNames.map(_.show.split("\\$").last)
case ClassInfo(_, _, _, decls, _) =>
decls.iterator
@@ -156,11 +156,11 @@ object factories {
constructors(sym).head
def paramLists(tpe: Type)(implicit ctx: Context): List[ParamList] = tpe match {
- case pt: PolyType =>
+ case pt: TypeLambda =>
paramLists(pt.resultType)
case mt: MethodType =>
- ParamListImpl(mt.paramNames.zip(mt.paramTypes).map { case (name, tpe) =>
+ ParamListImpl(mt.paramNames.zip(mt.paramInfos).map { case (name, tpe) =>
NamedReference(
name.decode.toString,
returnType(tpe),
@@ -169,13 +169,13 @@ object factories {
)
}, mt.isImplicit) :: paramLists(mt.resultType)
- case mp: MethodParam =>
+ case mp: TermParamRef =>
paramLists(mp.underlying)
case annot: AnnotatedType =>
paramLists(annot.tpe)
- case (_: PolyParam | _: RefinedType | _: TypeRef | _: ThisType |
+ case (_: TypeParamRef | _: RefinedType | _: TypeRef | _: ThisType |
_: ExprType | _: OrType | _: AndType | _: HKApply |
_: TermRef | _: ConstantType) =>
Nil // return types should not be in the paramlist
diff --git a/docs/docs/internals/syntax.md b/docs/docs/internals/syntax.md
index 7f06cdc2a..e4285e20f 100644
--- a/docs/docs/internals/syntax.md
+++ b/docs/docs/internals/syntax.md
@@ -289,7 +289,9 @@ TemplateBody ::= [nl] ‘{’ [SelfType] TemplateStat {semi TemplateStat}
TemplateStat ::= Import
| {Annotation [nl]} {Modifier} Def
| {Annotation [nl]} {Modifier} Dcl
+ | EnumCaseStat
| Expr1
+ |
SelfType ::= id [‘:’ InfixType] ‘=>’ ValDef(_, name, tpt, _)
| ‘this’ ‘:’ InfixType ‘=>’
@@ -328,13 +330,20 @@ DefDef ::= DefSig [‘:’ Type] ‘=’ Expr
| ‘this’ DefParamClause DefParamClauses DefDef(_, <init>, Nil, vparamss, EmptyTree, expr | Block)
(‘=’ ConstrExpr | [nl] ConstrBlock)
-TmplDef ::= ([‘case’] ‘class’ | ‘trait’) ClassDef
+TmplDef ::= ([‘case’ | `enum'] ‘class’ | trait’) ClassDef
| [‘case’] ‘object’ ObjectDef
-ClassDef ::= id [ClsTypeParamClause] ClassDef(mods, name, tparams, templ)
- [ConstrMods] ClsParamClauses TemplateOpt with DefDef(_, <init>, Nil, vparamss, EmptyTree, EmptyTree) as first stat
+ | `enum' EnumDef
+ClassDef ::= id ClassConstr TemplateOpt ClassDef(mods, name, tparams, templ)
+ClassConstr ::= [ClsTypeParamClause] [ConstrMods] ClsParamClauses with DefDef(_, <init>, Nil, vparamss, EmptyTree, EmptyTree) as first stat
ConstrMods ::= AccessModifier
| Annotation {Annotation} (AccessModifier | ‘this’)
ObjectDef ::= id TemplateOpt ModuleDef(mods, name, template) // no constructor
+EnumDef ::= id ClassConstr [`extends' [ConstrApps]] EnumDef(mods, name, tparams, template)
+ [nl] ‘{’ EnumCaseStat {semi EnumCaseStat} ‘}’
+EnumCaseStat ::= {Annotation [nl]} {Modifier} EnumCase
+EnumCase ::= `case' (EnumClassDef | ObjectDef | ids)
+EnumClassDef ::= id [ClsTpeParamClause | ClsParamClause] ClassDef(mods, name, tparams, templ)
+ ClsParamClauses TemplateOpt
TemplateOpt ::= [‘extends’ Template | [nl] TemplateBody]
Template ::= ConstrApps [TemplateBody] | TemplateBody Template(constr, parents, self, stats)
ConstrApps ::= ConstrApp {‘with’ ConstrApp}
diff --git a/library/src/scala/Enum.scala b/library/src/scala/Enum.scala
new file mode 100644
index 000000000..7d2eefb3d
--- /dev/null
+++ b/library/src/scala/Enum.scala
@@ -0,0 +1,8 @@
+package scala
+
+/** A base trait of all enum classes */
+trait Enum {
+
+ /** A number uniquely identifying a case of an enum */
+ def enumTag: Int
+}
diff --git a/library/src/scala/runtime/EnumValues.scala b/library/src/scala/runtime/EnumValues.scala
new file mode 100644
index 000000000..6f9d907b3
--- /dev/null
+++ b/library/src/scala/runtime/EnumValues.scala
@@ -0,0 +1,21 @@
+package scala.runtime
+
+import scala.collection.immutable.Map
+
+class EnumValues[E <: Enum] {
+ private var myMap: Map[Int, E] = Map()
+ private var fromNameCache: Map[String, E] = null
+
+ def register(v: E) = {
+ require(!myMap.contains(v.enumTag))
+ myMap = myMap.updated(v.enumTag, v)
+ fromNameCache = null
+ }
+
+ def fromInt: Map[Int, E] = myMap
+ def fromName: Map[String, E] = {
+ if (fromNameCache == null) fromNameCache = myMap.values.map(v => v.toString -> v).toMap
+ fromNameCache
+ }
+ def values: Iterable[E] = myMap.values
+}
diff --git a/tests/neg/enums.scala b/tests/neg/enums.scala
new file mode 100644
index 000000000..108ec4a6c
--- /dev/null
+++ b/tests/neg/enums.scala
@@ -0,0 +1,20 @@
+enum List[+T] {
+ case Cons(x: T, xs: List[T])
+ case Snoc[U](xs: List[U], x: U) // error: case with type parameters needs extends clause
+}
+
+enum class X {
+ case Y // error: case not allowed here
+}
+
+enum E1[T] {
+ case C // error: cannot determine type argument
+}
+
+enum E2[+T, +U >: T] {
+ case C // error: cannot determine type argument
+}
+
+enum E3[-T <: Ordered[T]] {
+ case C // error: cannot determine type argument
+}
diff --git a/tests/neg/leak-type.scala b/tests/neg/leak-type.scala
new file mode 100644
index 000000000..30ecab70b
--- /dev/null
+++ b/tests/neg/leak-type.scala
@@ -0,0 +1,13 @@
+trait A {
+ private type Foo = Int
+
+
+ class Inner[T <: Foo] { // error: non-private type T refers to private type Foo in its type signature
+ def get: T = ???
+ }
+}
+class B extends A {
+ def foo(x: Inner[_]): Unit = {
+ val a = x.get // error: cannot resolve reference to type B(B.this).Foo
+ }
+}
diff --git a/tests/pos/enum-List-control.scala b/tests/pos/enum-List-control.scala
new file mode 100644
index 000000000..d9df176d1
--- /dev/null
+++ b/tests/pos/enum-List-control.scala
@@ -0,0 +1,14 @@
+abstract sealed class List[T] extends Enum
+object List {
+ final case class Cons[T](x: T, xs: List[T]) extends List[T] {
+ def enumTag = 0
+ }
+ final case class Nil[T]() extends List[T] {
+ def enumTag = 1
+ }
+}
+object Test {
+ import List._
+ val xs = Cons(1, Cons(2, Cons(3, Nil())))
+ def main(args: Array[String]) = println(xs)
+}
diff --git a/tests/pos/i1130.scala b/tests/pos/i1130.scala
index 8d71de5e8..c28eaa169 100644
--- a/tests/pos/i1130.scala
+++ b/tests/pos/i1130.scala
@@ -3,4 +3,6 @@ trait A {
def foo: Foo = 1
}
-class B extends A
+class B extends A {
+ foo
+}
diff --git a/tests/pos/leak-inferred.scala b/tests/pos/leak-inferred.scala
new file mode 100644
index 000000000..5d8a7e3bc
--- /dev/null
+++ b/tests/pos/leak-inferred.scala
@@ -0,0 +1,12 @@
+class A {
+ private val x = List(1,2)
+
+ val elem = x.head
+}
+
+class B extends A {
+ val a: Int = elem
+ // Without `checkNoPrivateLeaks`, we get:
+ // found: B.this.x.scala$collection$immutable$List$$A(B.this.elem)
+ // required: Int
+}
diff --git a/tests/pos/tailcall/i2024.scala b/tests/pos/tailcall/i2024.scala
new file mode 100644
index 000000000..aba1db2e5
--- /dev/null
+++ b/tests/pos/tailcall/i2024.scala
@@ -0,0 +1,4 @@
+object Test {
+// def main(args: Array[String]): Unit = { }
+ def assume[T]: Any = assume
+}
diff --git a/tests/pos/tailcall/return.scala b/tests/pos/tailcall/return.scala
index 454686c3d..3724b5b32 100644
--- a/tests/pos/tailcall/return.scala
+++ b/tests/pos/tailcall/return.scala
@@ -1,4 +1,4 @@
-object Test {
+object Return {
def foo(x: Int): Int = return 3
diff --git a/tests/run/enum-Color.check b/tests/run/enum-Color.check
new file mode 100644
index 000000000..865c47e49
--- /dev/null
+++ b/tests/run/enum-Color.check
@@ -0,0 +1,3 @@
+Red: 0
+Green: 1
+Blue: 2
diff --git a/tests/run/enum-Color.scala b/tests/run/enum-Color.scala
new file mode 100644
index 000000000..683d18d9e
--- /dev/null
+++ b/tests/run/enum-Color.scala
@@ -0,0 +1,11 @@
+enum Color {
+ case Red, Green, Blue
+}
+
+object Test {
+ def main(args: Array[String]) =
+ for (color <- Color.enumValues) {
+ println(s"$color: ${color.enumTag}")
+ assert(Color.enumValue(color.enumTag) eq color)
+ }
+}
diff --git a/tests/run/enum-HList.scala b/tests/run/enum-HList.scala
new file mode 100644
index 000000000..c019cb6cc
--- /dev/null
+++ b/tests/run/enum-HList.scala
@@ -0,0 +1,22 @@
+enum HLst {
+ case HCons[+Hd, +Tl <: HLst](hd: Hd, tl: Tl)
+ case HNil
+}
+
+object Test {
+ import HLst._
+ def length(hl: HLst): Int = hl match {
+ case HCons(_, tl) => 1 + length(tl)
+ case HNil => 0
+ }
+ def sumInts(hl: HLst): Int = hl match {
+ case HCons(x: Int, tl) => x + sumInts(tl)
+ case HCons(_, tl) => sumInts(tl)
+ case HNil => 0
+ }
+ def main(args: Array[String]) = {
+ val hl = HCons(1, HCons("A", HNil))
+ assert(length(hl) == 2, length(hl))
+ assert(sumInts(hl) == 1)
+ }
+}
diff --git a/tests/run/enum-List1.check b/tests/run/enum-List1.check
new file mode 100644
index 000000000..3ed5061b4
--- /dev/null
+++ b/tests/run/enum-List1.check
@@ -0,0 +1 @@
+Cons(1,Cons(2,Cons(3,Nil())))
diff --git a/tests/run/enum-List1.scala b/tests/run/enum-List1.scala
new file mode 100644
index 000000000..bb75bec4a
--- /dev/null
+++ b/tests/run/enum-List1.scala
@@ -0,0 +1,10 @@
+enum class List[T]
+object List {
+ case Cons(x: T, xs: List[T])
+ case Nil()
+}
+object Test {
+ import List._
+ val xs = Cons(1, Cons(2, Cons(3, Nil())))
+ def main(args: Array[String]) = println(xs)
+}
diff --git a/tests/run/enum-List2.check b/tests/run/enum-List2.check
new file mode 100644
index 000000000..1d4812de1
--- /dev/null
+++ b/tests/run/enum-List2.check
@@ -0,0 +1 @@
+Cons(1,Cons(2,Cons(3,Nil)))
diff --git a/tests/run/enum-List2.scala b/tests/run/enum-List2.scala
new file mode 100644
index 000000000..030de0f84
--- /dev/null
+++ b/tests/run/enum-List2.scala
@@ -0,0 +1,11 @@
+enum class List[+T]
+object List {
+ case Cons(x: T, xs: List[T])
+ case Nil extends List[Nothing]
+}
+object Test {
+ import List._
+ val xs = Cons(1, Cons(2, Cons(3, Nil)))
+ def main(args: Array[String]) = println(xs)
+}
+
diff --git a/tests/run/enum-List2a.check b/tests/run/enum-List2a.check
new file mode 100644
index 000000000..1d4812de1
--- /dev/null
+++ b/tests/run/enum-List2a.check
@@ -0,0 +1 @@
+Cons(1,Cons(2,Cons(3,Nil)))
diff --git a/tests/run/enum-List2a.scala b/tests/run/enum-List2a.scala
new file mode 100644
index 000000000..323a5587c
--- /dev/null
+++ b/tests/run/enum-List2a.scala
@@ -0,0 +1,11 @@
+enum class List[+T]
+object List {
+ case Cons(x: T, xs: List[T])
+ case Nil
+}
+object Test {
+ import List._
+ val xs = Cons(1, Cons(2, Cons(3, Nil)))
+ def main(args: Array[String]) = println(xs)
+}
+
diff --git a/tests/run/enum-List3.check b/tests/run/enum-List3.check
new file mode 100644
index 000000000..1d4812de1
--- /dev/null
+++ b/tests/run/enum-List3.check
@@ -0,0 +1 @@
+Cons(1,Cons(2,Cons(3,Nil)))
diff --git a/tests/run/enum-List3.scala b/tests/run/enum-List3.scala
new file mode 100644
index 000000000..e5ffe1a28
--- /dev/null
+++ b/tests/run/enum-List3.scala
@@ -0,0 +1,10 @@
+enum List[+T] {
+ case Cons(x: T, xs: List[T])
+ case Nil extends List[Nothing]
+}
+object Test {
+ import List._
+ val xs = Cons(1, Cons(2, Cons(3, Nil)))
+ def main(args: Array[String]) = println(xs)
+}
+
diff --git a/tests/run/enum-Option.scala b/tests/run/enum-Option.scala
new file mode 100644
index 000000000..76f5641b3
--- /dev/null
+++ b/tests/run/enum-Option.scala
@@ -0,0 +1,19 @@
+enum class Option[+T >: Null] extends Serializable {
+ def isDefined: Boolean
+}
+object Option {
+ def apply[T >: Null](x: T): Option[T] = if (x == null) None else Some(x)
+ case Some(x: T) {
+ def isDefined = true
+ }
+ case None {
+ def isDefined = false
+ }
+}
+
+object Test {
+ def main(args: Array[String]) = {
+ assert(Some(None).isDefined)
+ Option("22") match { case Option.Some(x) => assert(x == "22") }
+ }
+}
diff --git a/tests/run/enum-Tree.check b/tests/run/enum-Tree.check
new file mode 100644
index 000000000..02f5151be
--- /dev/null
+++ b/tests/run/enum-Tree.check
@@ -0,0 +1 @@
+If(IsZero(Pred(Succ(Zero))),Succ(Succ(Zero)),Pred(Pred(Zero))) --> 2
diff --git a/tests/run/enum-Tree.scala b/tests/run/enum-Tree.scala
new file mode 100644
index 000000000..ef5bd7a57
--- /dev/null
+++ b/tests/run/enum-Tree.scala
@@ -0,0 +1,29 @@
+enum Tree[T] {
+ case True extends Tree[Boolean]
+ case False extends Tree[Boolean]
+ case Zero extends Tree[Int]
+ case Succ(n: Tree[Int]) extends Tree[Int]
+ case Pred(n: Tree[Int]) extends Tree[Int]
+ case IsZero(n: Tree[Int]) extends Tree[Boolean]
+ case If(cond: Tree[Boolean], thenp: Tree[T], elsep: Tree[T])
+}
+
+object Test {
+ import Tree._
+
+ def eval[T](e: Tree[T]): T = e match {
+ case True => true
+ case False => false
+ case Zero => 0
+ case Succ(f) => eval(f) + 1
+ case Pred(f) => eval(f) - 1
+ case IsZero(f) => eval(f) == 0
+ case If(cond, thenp, elsep) => if (eval(cond)) eval(thenp) else eval(elsep)
+ }
+
+ val data = If(IsZero(Pred(Succ(Zero))), Succ(Succ(Zero)), Pred(Pred(Zero)))
+
+ def main(args: Array[String]) = {
+ println(s"$data --> ${eval(data)}")
+ }
+}
diff --git a/tests/run/enum-approx.scala b/tests/run/enum-approx.scala
new file mode 100644
index 000000000..7811b3909
--- /dev/null
+++ b/tests/run/enum-approx.scala
@@ -0,0 +1,22 @@
+enum class Fun[-T, +U >: Null] {
+ def f: T => U = null
+}
+object Fun {
+ case Identity[T, U >: Null](override val f: T => U) extends Fun[T, U]
+ case ConstNull {
+ override def f = x => null
+ }
+ case ConstNullClass() {
+ override def f = x => null
+ }
+ case ConstNullSimple
+}
+
+object Test {
+ def main(args: Array[String]) = {
+ val x: Null = Fun.ConstNull.f("abc")
+ val y: Null = Fun.ConstNullClass().f("abc")
+ assert(Fun.ConstNullSimple.f == null)
+ }
+}
+
diff --git a/tests/run/enumList2a.check b/tests/run/enumList2a.check
new file mode 100644
index 000000000..1d4812de1
--- /dev/null
+++ b/tests/run/enumList2a.check
@@ -0,0 +1 @@
+Cons(1,Cons(2,Cons(3,Nil)))
diff --git a/tests/run/generic/Color.scala b/tests/run/generic/Color.scala
index ed248295d..7f2a8818c 100644
--- a/tests/run/generic/Color.scala
+++ b/tests/run/generic/Color.scala
@@ -10,12 +10,17 @@ import Shapes._
*/
sealed trait Color extends Enum
-object Color extends EnumValues[Color](3) {
+object Color {
+
+ private val $values = new runtime.EnumValues[Color]
+ def valueOf = $values.fromInt
+ def withName = $values.fromName
+ def values = $values.values
private def $new(tag: Int, name: String) = new Color {
def enumTag = tag
override def toString = name
- registerEnumValue(this)
+ $values.register(this)
}
val Red: Color = $new(0, "Red")
@@ -25,6 +30,6 @@ object Color extends EnumValues[Color](3) {
implicit val ColorShape: Color `shaped` EnumValue[Color] =
new (Color `shaped` EnumValue[Color]) {
def toShape(x: Color) = EnumValue(x.enumTag)
- def fromShape(x: EnumValue[Color]) = Color.value(x.tag)
+ def fromShape(x: EnumValue[Color]) = Color.valueOf(x.tag)
}
-} \ No newline at end of file
+}
diff --git a/tests/run/generic/Enum.scala b/tests/run/generic/Enum.scala
deleted file mode 100644
index dbdbfe8eb..000000000
--- a/tests/run/generic/Enum.scala
+++ /dev/null
@@ -1,18 +0,0 @@
-package generic
-
-import Shapes.Singleton
-
-trait Enum {
- def enumTag: Int
-}
-
-trait FiniteEnum extends Enum
-
-abstract class EnumValues[E <: Enum](numVals: Int) {
- private var myValues = new Array[AnyRef](numVals)
-
- def registerEnumValue(v: E) =
- myValues(v.enumTag) = v
-
- def value: IndexedSeq[E] = (myValues: IndexedSeq[AnyRef]).asInstanceOf[IndexedSeq[E]]
-}
diff --git a/tests/run/generic/List.scala b/tests/run/generic/List.scala
index 3f3657656..bc01ce63f 100644
--- a/tests/run/generic/List.scala
+++ b/tests/run/generic/List.scala
@@ -46,7 +46,7 @@ object List0 {
}
}
-/** enum List[T] {
+/** enum List[+T] {
* case Cons(x: T, xs: List[T])
* case Nil extends List[Nothing]
* }
diff --git a/tests/run/generic/SearchResult.scala b/tests/run/generic/SearchResult.scala
index 1c86d1b4f..d4380a072 100644
--- a/tests/run/generic/SearchResult.scala
+++ b/tests/run/generic/SearchResult.scala
@@ -11,12 +11,17 @@ import Shapes._
*/
sealed trait SearchResult extends Enum
-object SearchResult extends EnumValues[SearchResult](3) {
+object SearchResult extends {
+
+ private val $values = new runtime.EnumValues[SearchResult]
+ def valueOf = $values.fromInt
+ def withName = $values.fromName
+ def values = $values.values
private def $new(tag: Int, name: String) = new SearchResult {
def enumTag = tag
override def toString = name
- registerEnumValue(this)
+ $values.register(this)
}
abstract case class Success(result: Color) extends SearchResult {
@@ -31,8 +36,8 @@ object SearchResult extends EnumValues[SearchResult](3) {
}
}
- val Diverging = $new(1, "Diverging")
- val NoMatch = $new(2, "NoMatch")
+ val Diverging: SearchResult = $new(1, "Diverging")
+ val NoMatch: SearchResult = $new(2, "NoMatch")
abstract case class Ambiguous(alt1: SearchResult, alt2: SearchResult) extends SearchResult {
def enumTag = 3
@@ -58,7 +63,7 @@ object SearchResult extends EnumValues[SearchResult](3) {
def fromShape(x: Sum[Success, Sum[Ambiguous, EnumValue[SearchResult]]]): SearchResult = x match {
case Fst(s) => s
case Snd(Fst(a)) => a
- case Snd(Snd(ev)) => value(ev.tag)
+ case Snd(Snd(ev)) => valueOf(ev.tag)
}
}
-} \ No newline at end of file
+}
diff --git a/tests/run/generic/Tree.scala b/tests/run/generic/Tree.scala
index f4e706944..673506b07 100644
--- a/tests/run/generic/Tree.scala
+++ b/tests/run/generic/Tree.scala
@@ -2,14 +2,14 @@ package generic
import Shapes._
-/** enum Tree[TS] {
+/** enum Tree[T] {
* case True extends Tree[Boolean]
* case False extends Tree[Boolean]
* case Zero extends Tree[Int]
* case Succ(n: Tree[Int]) extends Tree[Int]
* case Pred(n: Tree[Int]) extends Tree[Int]
* case IsZero(n: Tree[Int]) extends Tree[Boolean]
- * case If(cond: Boolean, thenp: Tree[T], elsep: Tree[T]) extends Tree[T]
+ * case If(cond: Boolean, thenp: Tree[T], elsep: Tree[T])
* }
*/
sealed trait Tree[TR] extends Enum
@@ -110,4 +110,4 @@ object Tree {
case Snd(Snd(_if)) => _if
}
}
-} \ No newline at end of file
+}
diff --git a/tests/run/planets.check b/tests/run/planets.check
new file mode 100644
index 000000000..feb6f737d
--- /dev/null
+++ b/tests/run/planets.check
@@ -0,0 +1,8 @@
+Your weight on MERCURY is 37.775761520093525
+Your weight on SATURN is 106.60155388115666
+Your weight on VENUS is 90.49990998410455
+Your weight on URANUS is 90.51271993894251
+Your weight on EARTH is 100.0
+Your weight on NEPTUNE is 113.83280724696579
+Your weight on MARS is 37.873718403712886
+Your weight on JUPITER is 253.05575254957407
diff --git a/tests/run/planets.scala b/tests/run/planets.scala
new file mode 100644
index 000000000..bcbfd7eeb
--- /dev/null
+++ b/tests/run/planets.scala
@@ -0,0 +1,26 @@
+enum class Planet(mass: Double, radius: Double) {
+ private final val G = 6.67300E-11
+ def surfaceGravity = G * mass / (radius * radius)
+ def surfaceWeight(otherMass: Double) = otherMass * surfaceGravity
+}
+object Planet {
+ case MERCURY extends Planet(3.303e+23, 2.4397e6)
+ case VENUS extends Planet(4.869e+24, 6.0518e6)
+ case EARTH extends Planet(5.976e+24, 6.37814e6)
+ case MARS extends Planet(6.421e+23, 3.3972e6)
+ case JUPITER extends Planet(1.9e+27, 7.1492e7)
+ case SATURN extends Planet(5.688e+26, 6.0268e7)
+ case URANUS extends Planet(8.686e+25, 2.5559e7)
+ case NEPTUNE extends Planet(1.024e+26, 2.4746e7)
+}
+object Test {
+ def main(args: Array[String]) = {
+ import Planet._
+ assert(enumValueNamed("SATURN") == SATURN)
+ assert(enumValue(2) == EARTH)
+ val earthWeight = 100
+ val mass = earthWeight/EARTH.surfaceGravity
+ for (p <- enumValues)
+ println(s"Your weight on $p is ${p.surfaceWeight(mass)}")
+ }
+}