aboutsummaryrefslogtreecommitdiff
path: root/compiler/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/src')
-rw-r--r--compiler/src/dotty/tools/backend/jvm/CollectEntryPoints.scala11
-rw-r--r--compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/ast/tpd.scala6
-rw-r--r--compiler/src/dotty/tools/dotc/config/Config.scala4
-rw-r--r--compiler/src/dotty/tools/dotc/config/JavaPlatform.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/config/Settings.scala3
-rw-r--r--compiler/src/dotty/tools/dotc/core/Denotations.scala18
-rw-r--r--compiler/src/dotty/tools/dotc/core/Signature.scala4
-rw-r--r--compiler/src/dotty/tools/dotc/core/SymDenotations.scala4
-rw-r--r--compiler/src/dotty/tools/dotc/core/Symbols.scala13
-rw-r--r--compiler/src/dotty/tools/dotc/core/TypeComparer.scala8
-rw-r--r--compiler/src/dotty/tools/dotc/core/TypeErasure.scala3
-rw-r--r--compiler/src/dotty/tools/dotc/core/Types.scala204
-rw-r--r--compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala10
-rw-r--r--compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala5
-rw-r--r--compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala8
-rw-r--r--compiler/src/dotty/tools/dotc/rewrite/Rewrites.scala3
-rw-r--r--compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala4
-rw-r--r--compiler/src/dotty/tools/dotc/transform/CollectEntryPoints.scala6
-rw-r--r--compiler/src/dotty/tools/dotc/transform/ElimByName.scala4
-rw-r--r--compiler/src/dotty/tools/dotc/transform/ElimRepeated.scala4
-rw-r--r--compiler/src/dotty/tools/dotc/transform/Erasure.scala13
-rw-r--r--compiler/src/dotty/tools/dotc/transform/ExpandSAMs.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala10
-rw-r--r--compiler/src/dotty/tools/dotc/transform/FirstTransform.scala21
-rw-r--r--compiler/src/dotty/tools/dotc/transform/FullParameterization.scala13
-rw-r--r--compiler/src/dotty/tools/dotc/transform/LambdaLift.scala4
-rw-r--r--compiler/src/dotty/tools/dotc/transform/LazyVals.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/transform/ParamForwarding.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/transform/SymUtils.scala6
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Applications.scala29
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Checking.scala20
-rw-r--r--compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala4
-rw-r--r--compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala6
-rw-r--r--compiler/src/dotty/tools/dotc/typer/ReTyper.scala4
-rw-r--r--compiler/src/dotty/tools/dotc/typer/RefChecks.scala12
-rw-r--r--compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala6
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Typer.scala16
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Variances.scala4
-rw-r--r--compiler/src/dotty/tools/io/Jar.scala3
-rw-r--r--compiler/src/strawman/collections/CollectionStrawMan6.scala2
41 files changed, 299 insertions, 206 deletions
diff --git a/compiler/src/dotty/tools/backend/jvm/CollectEntryPoints.scala b/compiler/src/dotty/tools/backend/jvm/CollectEntryPoints.scala
index 0add25f3b..abcbbbb83 100644
--- a/compiler/src/dotty/tools/backend/jvm/CollectEntryPoints.scala
+++ b/compiler/src/dotty/tools/backend/jvm/CollectEntryPoints.scala
@@ -49,7 +49,7 @@ class CollectEntryPoints extends MiniPhaseTransform {
object CollectEntryPoints{
def isJavaMainMethod(sym: Symbol)(implicit ctx: Context) = {
(sym.name == nme.main) && (sym.info match {
- case r@MethodType(_, List(defn.ArrayOf(t))) =>
+ case r@MethodTpe(_, List(defn.ArrayOf(t)), _) =>
(t.widenDealias =:= defn.StringType) && (
r.resultType.widenDealias =:= defn.UnitType)
case _ => false
@@ -81,9 +81,8 @@ object CollectEntryPoints{
val possibles = if (sym.flags is Flags.Module) (toDenot(sym).info nonPrivateMember nme.main).alternatives else Nil
val hasApproximate = possibles exists { m =>
m.info match {
- case MethodType(_, p :: Nil) =>
- p.typeSymbol == defn.ArrayClass
- case _ => false
+ case MethodTpe(_, p :: Nil, _) => p.typeSymbol == defn.ArrayClass
+ case _ => false
}
}
// At this point it's a module with a main-looking method, so either succeed or warn that it isn't.
@@ -108,8 +107,8 @@ object CollectEntryPoints{
toDenot(m.symbol).info match {
case t: PolyType =>
fail("main methods cannot be generic.")
- case t@MethodType(paramNames, paramTypes) =>
- if (t.resultType :: paramTypes exists (_.typeSymbol.isAbstractType))
+ case MethodTpe(paramNames, paramTypes, resultType) =>
+ if (resultType :: paramTypes exists (_.typeSymbol.isAbstractType))
fail("main methods cannot refer to type parameters or abstract types.", m.symbol.pos)
else
isJavaMainMethod(m.symbol) || fail("main method must have exact signature (Array[String])Unit", m.symbol.pos)
diff --git a/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala b/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala
index 51fa15706..77e979e4d 100644
--- a/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala
+++ b/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala
@@ -531,7 +531,7 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma
tree match {
case Apply(fun, args) =>
fun.tpe.widen match {
- case MethodType(names, _) =>
+ case MethodType(names) =>
names zip args
}
}
diff --git a/compiler/src/dotty/tools/dotc/ast/tpd.scala b/compiler/src/dotty/tools/dotc/ast/tpd.scala
index e5904156f..cbb256dd0 100644
--- a/compiler/src/dotty/tools/dotc/ast/tpd.scala
+++ b/compiler/src/dotty/tools/dotc/ast/tpd.scala
@@ -185,12 +185,12 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
}
def valueParamss(tp: Type): (List[List[TermSymbol]], Type) = tp match {
- case tp @ MethodType(paramNames, paramTypes) =>
+ case tp: MethodType =>
def valueParam(name: TermName, info: Type): TermSymbol = {
val maybeImplicit = if (tp.isInstanceOf[ImplicitMethodType]) Implicit else EmptyFlags
ctx.newSymbol(sym, name, TermParam | maybeImplicit, info)
}
- val params = (paramNames, paramTypes).zipped.map(valueParam)
+ val params = (tp.paramNames, tp.paramTypes).zipped.map(valueParam)
val (paramss, rtp) = valueParamss(tp.instantiate(params map (_.termRef)))
(params :: paramss, rtp)
case tp => (Nil, tp.widenExpr)
@@ -607,7 +607,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
* owner to `to`, and continue until a non-weak owner is reached.
*/
def changeOwner(from: Symbol, to: Symbol)(implicit ctx: Context): ThisTree = {
- def loop(from: Symbol, froms: List[Symbol], tos: List[Symbol]): ThisTree = {
+ @tailrec def loop(from: Symbol, froms: List[Symbol], tos: List[Symbol]): ThisTree = {
if (from.isWeakOwner && !from.owner.isClass)
loop(from.owner, from :: froms, to :: tos)
else {
diff --git a/compiler/src/dotty/tools/dotc/config/Config.scala b/compiler/src/dotty/tools/dotc/config/Config.scala
index dc56ad8b8..903efd794 100644
--- a/compiler/src/dotty/tools/dotc/config/Config.scala
+++ b/compiler/src/dotty/tools/dotc/config/Config.scala
@@ -88,6 +88,10 @@ object Config {
*/
final val checkHKApplications = false
+ /** If this flag is set, method types are checked for valid parameter references
+ */
+ final val checkMethodTypes = false
+
/** The recursion depth for showing a summarized string */
final val summarizeDepth = 2
diff --git a/compiler/src/dotty/tools/dotc/config/JavaPlatform.scala b/compiler/src/dotty/tools/dotc/config/JavaPlatform.scala
index 59201687a..8bc18c387 100644
--- a/compiler/src/dotty/tools/dotc/config/JavaPlatform.scala
+++ b/compiler/src/dotty/tools/dotc/config/JavaPlatform.scala
@@ -23,7 +23,7 @@ class JavaPlatform extends Platform {
// The given symbol is a method with the right name and signature to be a runnable java program.
def isJavaMainMethod(sym: SymDenotation)(implicit ctx: Context) =
(sym.name == nme.main) && (sym.info match {
- case t@MethodType(_, defn.ArrayOf(el) :: Nil) => el =:= defn.StringType && (t.resultType isRef defn.UnitClass)
+ case MethodTpe(_, defn.ArrayOf(el) :: Nil, restpe) => el =:= defn.StringType && (restpe isRef defn.UnitClass)
case _ => false
})
diff --git a/compiler/src/dotty/tools/dotc/config/Settings.scala b/compiler/src/dotty/tools/dotc/config/Settings.scala
index 06ad2b84d..264388c03 100644
--- a/compiler/src/dotty/tools/dotc/config/Settings.scala
+++ b/compiler/src/dotty/tools/dotc/config/Settings.scala
@@ -5,6 +5,7 @@ import collection.mutable.{ ArrayBuffer }
import scala.util.{ Try, Success, Failure }
import reflect.ClassTag
import core.Contexts._
+import scala.annotation.tailrec
// import annotation.unchecked
// Dotty deviation: Imports take precedence over definitions in enclosing package
// (Note that @unchecked is in scala, not annotation, so annotation.unchecked gives
@@ -216,7 +217,7 @@ object Settings {
case "--" :: args =>
checkDependencies(stateWithArgs(skipped ++ args))
case x :: _ if x startsWith "-" =>
- def loop(settings: List[Setting[_]]): ArgsSummary = settings match {
+ @tailrec def loop(settings: List[Setting[_]]): ArgsSummary = settings match {
case setting :: settings1 =>
val state1 = setting.tryToSet(state)
if (state1 ne state) processArguments(state1, processAll, skipped)
diff --git a/compiler/src/dotty/tools/dotc/core/Denotations.scala b/compiler/src/dotty/tools/dotc/core/Denotations.scala
index 99c688d50..f726cd0d1 100644
--- a/compiler/src/dotty/tools/dotc/core/Denotations.scala
+++ b/compiler/src/dotty/tools/dotc/core/Denotations.scala
@@ -308,13 +308,13 @@ object Denotations {
case tp2: TypeBounds if tp2 contains tp1 => tp1
case _ => mergeConflict(tp1, tp2)
}
- case tp1 @ MethodType(names1, formals1) if isTerm =>
+ case tp1: MethodType if isTerm =>
tp2 match {
- case tp2 @ MethodType(names2, formals2) if ctx.typeComparer.matchingParams(formals1, formals2, tp1.isJava, tp2.isJava) &&
+ case tp2: MethodType if ctx.typeComparer.matchingParams(tp1.paramTypes, tp2.paramTypes, tp1.isJava, tp2.isJava) &&
tp1.isImplicit == tp2.isImplicit =>
tp1.derivedMethodType(
- mergeNames(names1, names2, nme.syntheticParamName),
- formals1,
+ mergeNames(tp1.paramNames, tp2.paramNames, nme.syntheticParamName),
+ tp1.paramTypes,
infoMeet(tp1.resultType, tp2.resultType.subst(tp2, tp1)))
case _ =>
mergeConflict(tp1, tp2)
@@ -471,14 +471,14 @@ object Denotations {
case tp2: TypeBounds if tp2 contains tp1 => tp2
case _ => mergeConflict(tp1, tp2)
}
- case tp1 @ MethodType(names1, formals1) =>
+ case tp1: MethodType =>
tp2 match {
- case tp2 @ MethodType(names2, formals2)
- if ctx.typeComparer.matchingParams(formals1, formals2, tp1.isJava, tp2.isJava) &&
+ case tp2: MethodType
+ if ctx.typeComparer.matchingParams(tp1.paramTypes, tp2.paramTypes, tp1.isJava, tp2.isJava) &&
tp1.isImplicit == tp2.isImplicit =>
tp1.derivedMethodType(
- mergeNames(names1, names2, nme.syntheticParamName),
- formals1, tp1.resultType | tp2.resultType.subst(tp2, tp1))
+ mergeNames(tp1.paramNames, tp2.paramNames, nme.syntheticParamName),
+ tp1.paramTypes, tp1.resultType | tp2.resultType.subst(tp2, tp1))
case _ =>
mergeConflict(tp1, tp2)
}
diff --git a/compiler/src/dotty/tools/dotc/core/Signature.scala b/compiler/src/dotty/tools/dotc/core/Signature.scala
index b2e627cbe..fcd1e2376 100644
--- a/compiler/src/dotty/tools/dotc/core/Signature.scala
+++ b/compiler/src/dotty/tools/dotc/core/Signature.scala
@@ -4,6 +4,8 @@ package core
import Names._, Types._, Contexts._, StdNames._
import TypeErasure.sigName
+import scala.annotation.tailrec
+
/** The signature of a denotation.
* Overloaded denotations with the same name are distinguished by
* their signatures. A signature of a method (of type PolyType,MethodType, or ExprType) is
@@ -41,7 +43,7 @@ case class Signature(paramsSig: List[TypeName], resSig: TypeName) {
* equal or on of them is tpnme.Uninstantiated.
*/
final def consistentParams(that: Signature): Boolean = {
- def loop(names1: List[TypeName], names2: List[TypeName]): Boolean =
+ @tailrec def loop(names1: List[TypeName], names2: List[TypeName]): Boolean =
if (names1.isEmpty) names2.isEmpty
else names2.nonEmpty && consistent(names1.head, names2.head) && loop(names1.tail, names2.tail)
loop(this.paramsSig, that.paramsSig)
diff --git a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala
index 326f0e39e..db96463e0 100644
--- a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala
+++ b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala
@@ -1044,7 +1044,7 @@ object SymDenotations {
* pre: `this.owner` is in the base class sequence of `base`.
*/
final def superSymbolIn(base: Symbol)(implicit ctx: Context): Symbol = {
- def loop(bcs: List[ClassSymbol]): Symbol = bcs match {
+ @tailrec def loop(bcs: List[ClassSymbol]): Symbol = bcs match {
case bc :: bcs1 =>
val sym = matchingDecl(bcs.head, base.thisType)
.suchThat(alt => !(alt is Deferred)).symbol
@@ -1060,7 +1060,7 @@ object SymDenotations {
* (2) it is abstract override and its super symbol in `base` is
* nonexistent or incomplete.
*/
- final def isIncompleteIn(base: Symbol)(implicit ctx: Context): Boolean =
+ @tailrec final def isIncompleteIn(base: Symbol)(implicit ctx: Context): Boolean =
(this is Deferred) ||
(this is AbsOverride) && {
val supersym = superSymbolIn(base)
diff --git a/compiler/src/dotty/tools/dotc/core/Symbols.scala b/compiler/src/dotty/tools/dotc/core/Symbols.scala
index c5e064478..33aba4d13 100644
--- a/compiler/src/dotty/tools/dotc/core/Symbols.scala
+++ b/compiler/src/dotty/tools/dotc/core/Symbols.scala
@@ -252,7 +252,7 @@ trait Symbols { this: Context =>
/** Create a class constructor symbol for given class `cls`. */
def newConstructor(cls: ClassSymbol, flags: FlagSet, paramNames: List[TermName], paramTypes: List[Type], privateWithin: Symbol = NoSymbol, coord: Coord = NoCoord) =
- newSymbol(cls, nme.CONSTRUCTOR, flags | Method, MethodType(paramNames, paramTypes)(_ => cls.typeRef), privateWithin, coord)
+ newSymbol(cls, nme.CONSTRUCTOR, flags | Method, MethodType(paramNames, paramTypes, cls.typeRef), privateWithin, coord)
/** Create an empty default constructor symbol for given class `cls`. */
def newDefaultConstructor(cls: ClassSymbol) =
@@ -496,12 +496,15 @@ object Symbols {
final def sourceFile(implicit ctx: Context): AbstractFile = {
val file = associatedFile
if (file != null && !file.path.endsWith("class")) file
- else denot.topLevelClass.getAnnotation(defn.SourceFileAnnot) match {
- case Some(sourceAnnot) => sourceAnnot.argumentConstant(0) match {
- case Some(Constant(path: String)) => AbstractFile.getFile(path)
+ else {
+ val topLevelCls = denot.topLevelClass(ctx.withPhaseNoLater(ctx.flattenPhase))
+ topLevelCls.getAnnotation(defn.SourceFileAnnot) match {
+ case Some(sourceAnnot) => sourceAnnot.argumentConstant(0) match {
+ case Some(Constant(path: String)) => AbstractFile.getFile(path)
+ case none => null
+ }
case none => null
}
- case none => null
}
}
diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala
index b61fccf31..21a12dbb7 100644
--- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala
+++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala
@@ -484,11 +484,11 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
case _ =>
}
either(isSubType(tp1, tp21), isSubType(tp1, tp22)) || fourthTry(tp1, tp2)
- case tp2 @ MethodType(_, formals2) =>
+ case tp2: MethodType =>
def compareMethod = tp1 match {
- case tp1 @ MethodType(_, formals1) =>
+ case tp1: MethodType =>
(tp1.signature consistentParams tp2.signature) &&
- matchingParams(formals1, formals2, tp1.isJava, tp2.isJava) &&
+ matchingParams(tp1.paramTypes, tp2.paramTypes, tp1.isJava, tp2.isJava) &&
(tp1.isImplicit == tp2.isImplicit) &&
isSubType(tp1.resultType, tp2.resultType.subst(tp2, tp1))
case _ =>
@@ -503,7 +503,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
// as members of the same type. And it seems most logical to take
// ()T <:< => T, since everything one can do with a => T one can
// also do with a ()T by automatic () insertion.
- case tp1 @ MethodType(Nil, _) => isSubType(tp1.resultType, restpe2)
+ case tp1 @ MethodType(Nil) => isSubType(tp1.resultType, restpe2)
case _ => isSubType(tp1.widenExpr, restpe2)
}
compareExpr
diff --git a/compiler/src/dotty/tools/dotc/core/TypeErasure.scala b/compiler/src/dotty/tools/dotc/core/TypeErasure.scala
index 10587afd5..fe3396fcb 100644
--- a/compiler/src/dotty/tools/dotc/core/TypeErasure.scala
+++ b/compiler/src/dotty/tools/dotc/core/TypeErasure.scala
@@ -10,6 +10,7 @@ import dotc.transform.ExplicitOuter._
import dotc.transform.ValueClasses._
import util.DotClass
import Definitions.MaxImplementedFunctionArity
+import scala.annotation.tailrec
/** Erased types are:
*
@@ -244,7 +245,7 @@ object TypeErasure {
case JavaArrayType(_) => defn.ObjectType
case _ =>
val cls2 = tp2.classSymbol
- def loop(bcs: List[ClassSymbol], bestSoFar: ClassSymbol): ClassSymbol = bcs match {
+ @tailrec def loop(bcs: List[ClassSymbol], bestSoFar: ClassSymbol): ClassSymbol = bcs match {
case bc :: bcs1 =>
if (cls2.derivesFrom(bc)) {
val newBest = if (bestSoFar.derivesFrom(bc)) bestSoFar else bc
diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala
index 271dcda7c..abc496ec0 100644
--- a/compiler/src/dotty/tools/dotc/core/Types.scala
+++ b/compiler/src/dotty/tools/dotc/core/Types.scala
@@ -106,7 +106,7 @@ object Types {
final def isValueTypeOrLambda: Boolean = isValueType || this.isInstanceOf[PolyType]
/** Does this type denote a stable reference (i.e. singleton type)? */
- final def isStable(implicit ctx: Context): Boolean = stripTypeVar match {
+ @tailrec final def isStable(implicit ctx: Context): Boolean = stripTypeVar match {
case tp: TermRef => tp.termSymbol.isStable && tp.prefix.isStable
case _: SingletonType | NoPrefix => true
case tp: RefinedOrRecType => tp.parent.isStable
@@ -154,16 +154,16 @@ object Types {
/** Is this type an instance of a non-bottom subclass of the given class `cls`? */
final def derivesFrom(cls: Symbol)(implicit ctx: Context): Boolean = {
- def loop(tp: Type) = tp match {
+ def loop(tp: Type): Boolean = tp match {
case tp: TypeRef =>
val sym = tp.symbol
- if (sym.isClass) sym.derivesFrom(cls) else tp.superType.derivesFrom(cls)
+ if (sym.isClass) sym.derivesFrom(cls) else loop(tp.superType): @tailrec
case tp: TypeProxy =>
- tp.underlying.derivesFrom(cls)
+ loop(tp.underlying): @tailrec
case tp: AndType =>
- tp.tp1.derivesFrom(cls) || tp.tp2.derivesFrom(cls)
+ loop(tp.tp1) || loop(tp.tp2): @tailrec
case tp: OrType =>
- tp.tp1.derivesFrom(cls) && tp.tp2.derivesFrom(cls)
+ loop(tp.tp1) && loop(tp.tp2): @tailrec
case tp: JavaArrayType =>
cls == defn.ObjectClass
case _ =>
@@ -189,7 +189,7 @@ object Types {
final def isErroneous(implicit ctx: Context): Boolean = existsPart(_.isError, forceLazy = false)
/** Does the type carry an annotation that is an instance of `cls`? */
- final def hasAnnotation(cls: ClassSymbol)(implicit ctx: Context): Boolean = stripTypeVar match {
+ @tailrec final def hasAnnotation(cls: ClassSymbol)(implicit ctx: Context): Boolean = stripTypeVar match {
case AnnotatedType(tp, annot) => (annot matches cls) || (tp hasAnnotation cls)
case _ => false
}
@@ -217,14 +217,14 @@ object Types {
*/
def isVarArgsMethod(implicit ctx: Context): Boolean = this match {
case tp: PolyType => tp.resultType.isVarArgsMethod
- case MethodType(_, paramTypes) => paramTypes.nonEmpty && paramTypes.last.isRepeatedParam
+ case mt: MethodType => mt.paramTypes.nonEmpty && mt.paramTypes.last.isRepeatedParam
case _ => false
}
/** Is this the type of a method with a leading empty parameter list?
*/
def isNullaryMethod(implicit ctx: Context): Boolean = this match {
- case MethodType(Nil, _) => true
+ case MethodType(Nil) => true
case tp: PolyType => tp.resultType.isNullaryMethod
case _ => false
}
@@ -278,7 +278,7 @@ object Types {
// ----- Associated symbols ----------------------------------------------
/** The type symbol associated with the type */
- final def typeSymbol(implicit ctx: Context): Symbol = this match {
+ @tailrec final def typeSymbol(implicit ctx: Context): Symbol = this match {
case tp: TypeRef => tp.symbol
case tp: ClassInfo => tp.cls
// case ThisType(cls) => cls // needed?
@@ -293,16 +293,16 @@ object Types {
*/
final def classSymbol(implicit ctx: Context): Symbol = this match {
case ConstantType(constant) =>
- constant.tpe.classSymbol
+ constant.tpe.classSymbol: @tailrec
case tp: TypeRef =>
val sym = tp.symbol
- if (sym.isClass) sym else tp.superType.classSymbol
+ if (sym.isClass) sym else tp.superType.classSymbol: @tailrec
case tp: ClassInfo =>
tp.cls
case tp: SingletonType =>
NoSymbol
case tp: TypeProxy =>
- tp.underlying.classSymbol
+ tp.underlying.classSymbol: @tailrec
case AndType(l, r) =>
val lsym = l.classSymbol
val rsym = r.classSymbol
@@ -326,9 +326,9 @@ object Types {
tp.cls :: Nil
case tp: TypeRef =>
val sym = tp.symbol
- if (sym.isClass) sym.asClass :: Nil else tp.superType.classSymbols
+ if (sym.isClass) sym.asClass :: Nil else tp.superType.classSymbols: @tailrec
case tp: TypeProxy =>
- tp.underlying.classSymbols
+ tp.underlying.classSymbols: @tailrec
case AndType(l, r) =>
l.classSymbols union r.classSymbols
case OrType(l, r) =>
@@ -338,7 +338,7 @@ object Types {
}
/** The term symbol associated with the type */
- final def termSymbol(implicit ctx: Context): Symbol = this match {
+ @tailrec final def termSymbol(implicit ctx: Context): Symbol = this match {
case tp: TermRef => tp.symbol
case tp: TypeProxy => tp.underlying.termSymbol
case _ => NoSymbol
@@ -369,11 +369,11 @@ object Types {
* Defined by ClassInfo, inherited by type proxies.
* Empty scope for all other types.
*/
- final def decls(implicit ctx: Context): Scope = this match {
+ @tailrec final def decls(implicit ctx: Context): Scope = this match {
case tp: ClassInfo =>
tp.decls
case tp: TypeProxy =>
- tp.underlying.decls
+ tp.underlying.decls: @tailrec
case _ =>
EmptyScope
}
@@ -395,7 +395,7 @@ object Types {
* name, as seen from prefix type `pre`. Declarations that have a flag
* in `excluded` are omitted.
*/
- final def findDecl(name: Name, excluded: FlagSet)(implicit ctx: Context): Denotation = this match {
+ @tailrec final def findDecl(name: Name, excluded: FlagSet)(implicit ctx: Context): Denotation = this match {
case tp: ClassInfo =>
tp.decls.denotsNamed(name).filterExcluded(excluded).toDenot(NoPrefix)
case tp: TypeProxy =>
@@ -615,7 +615,7 @@ object Types {
val ns = tp.parent.memberNames(keepOnly, pre)
if (keepOnly(pre, tp.refinedName)) ns + tp.refinedName else ns
case tp: TypeProxy =>
- tp.underlying.memberNames(keepOnly, pre)
+ tp.underlying.memberNames(keepOnly, pre): @tailrec
case tp: AndType =>
tp.tp1.memberNames(keepOnly, pre) | tp.tp2.memberNames(keepOnly, pre)
case tp: OrType =>
@@ -732,7 +732,7 @@ object Types {
*/
final def overrides(that: Type)(implicit ctx: Context) = {
def result(tp: Type): Type = tp match {
- case ExprType(_) | MethodType(Nil, _) => tp.resultType
+ case ExprType(_) | MethodType(Nil) => tp.resultType
case _ => tp
}
(this frozen_<:< that) || {
@@ -823,7 +823,7 @@ object Types {
* def o: Outer
* <o.x.type>.widen = o.C
*/
- final def widen(implicit ctx: Context): Type = widenSingleton match {
+ @tailrec final def widen(implicit ctx: Context): Type = widenSingleton match {
case tp: ExprType => tp.resultType.widen
case tp => tp
}
@@ -831,7 +831,7 @@ object Types {
/** Widen from singleton type to its underlying non-singleton
* base type by applying one or more `underlying` dereferences.
*/
- final def widenSingleton(implicit ctx: Context): Type = stripTypeVar match {
+ @tailrec final def widenSingleton(implicit ctx: Context): Type = stripTypeVar match {
case tp: SingletonType if !tp.isOverloaded => tp.underlying.widenSingleton
case _ => this
}
@@ -839,7 +839,7 @@ object Types {
/** Widen from TermRef to its underlying non-termref
* base type, while also skipping Expr types.
*/
- final def widenTermRefExpr(implicit ctx: Context): Type = stripTypeVar match {
+ @tailrec final def widenTermRefExpr(implicit ctx: Context): Type = stripTypeVar match {
case tp: TermRef if !tp.isOverloaded => tp.underlying.widenExpr.widenTermRefExpr
case _ => this
}
@@ -853,7 +853,7 @@ object Types {
}
/** Widen type if it is unstable (i.e. an ExprType, or TermRef to unstable symbol */
- final def widenIfUnstable(implicit ctx: Context): Type = stripTypeVar match {
+ @tailrec final def widenIfUnstable(implicit ctx: Context): Type = stripTypeVar match {
case tp: ExprType => tp.resultType.widenIfUnstable
case tp: TermRef if !tp.symbol.isStable => tp.underlying.widenIfUnstable
case _ => this
@@ -876,20 +876,20 @@ object Types {
case tp: TypeRef =>
if (tp.symbol.isClass) tp
else tp.info match {
- case TypeAlias(tp) => tp.dealias(keepAnnots)
+ case TypeAlias(tp) => tp.dealias(keepAnnots): @tailrec
case _ => tp
}
case tp: TypeVar =>
val tp1 = tp.instanceOpt
- if (tp1.exists) tp1.dealias(keepAnnots) else tp
+ if (tp1.exists) tp1.dealias(keepAnnots): @tailrec else tp
case tp: AnnotatedType =>
val tp1 = tp.tpe.dealias(keepAnnots)
if (keepAnnots) tp.derivedAnnotatedType(tp1, tp.annot) else tp1
case tp: LazyRef =>
- tp.ref.dealias(keepAnnots)
+ tp.ref.dealias(keepAnnots): @tailrec
case app @ HKApply(tycon, args) =>
val tycon1 = tycon.dealias(keepAnnots)
- if (tycon1 ne tycon) app.superType.dealias(keepAnnots)
+ if (tycon1 ne tycon) app.superType.dealias(keepAnnots): @tailrec
else this
case _ => this
}
@@ -909,7 +909,7 @@ object Types {
dealias(keepAnnots = false)
/** Perform successive widenings and dealiasings until none can be applied anymore */
- final def widenDealias(implicit ctx: Context): Type = {
+ @tailrec final def widenDealias(implicit ctx: Context): Type = {
val res = this.widen.dealias
if (res eq this) res else res.widenDealias
}
@@ -992,7 +992,7 @@ object Types {
* (*) normalizes means: follow instantiated typevars and aliases.
*/
def lookupRefined(name: Name)(implicit ctx: Context): Type = {
- def loop(pre: Type): Type = pre.stripTypeVar match {
+ @tailrec def loop(pre: Type): Type = pre.stripTypeVar match {
case pre: RefinedType =>
pre.refinedInfo match {
case TypeAlias(alias) =>
@@ -1000,14 +1000,14 @@ object Types {
case _ => loop(pre.parent)
}
case pre: RecType =>
- val candidate = loop(pre.parent)
+ val candidate = pre.parent.lookupRefined(name)
if (candidate.exists && !pre.isReferredToBy(candidate)) {
//println(s"lookupRefined ${this.toString} . $name, pre: $pre ---> $candidate / ${candidate.toString}")
candidate
}
else NoType
case SkolemType(tp) =>
- tp.lookupRefined(name)
+ loop(tp)
case pre: WildcardType =>
WildcardType
case pre: TypeRef =>
@@ -1047,7 +1047,7 @@ object Types {
* Inherited by all other type proxies.
* `NoType` for all other types.
*/
- final def normalizedPrefix(implicit ctx: Context): Type = this match {
+ @tailrec final def normalizedPrefix(implicit ctx: Context): Type = this match {
case tp: NamedType =>
if (tp.symbol.info.isAlias) tp.info.normalizedPrefix else tp.prefix
case tp: ClassInfo =>
@@ -1103,14 +1103,14 @@ object Types {
/** The parameter types in the first parameter section of a generic type or MethodType, Empty list for others */
- final def firstParamTypes(implicit ctx: Context): List[Type] = this match {
+ @tailrec final def firstParamTypes(implicit ctx: Context): List[Type] = this match {
case mt: MethodType => mt.paramTypes
case pt: PolyType => pt.resultType.firstParamTypes
case _ => Nil
}
/** Is this either not a method at all, or a parameterless method? */
- final def isParameterless(implicit ctx: Context): Boolean = this match {
+ @tailrec final def isParameterless(implicit ctx: Context): Boolean = this match {
case mt: MethodType => false
case pt: PolyType => pt.resultType.isParameterless
case _ => true
@@ -1219,8 +1219,8 @@ object Types {
* when forming the function type.
*/
def toFunctionType(dropLast: Int = 0)(implicit ctx: Context): Type = this match {
- case mt @ MethodType(_, formals) if !mt.isDependent || ctx.mode.is(Mode.AllowDependentFunctions) =>
- val formals1 = if (dropLast == 0) formals else formals dropRight dropLast
+ case mt: MethodType if !mt.isDependent || ctx.mode.is(Mode.AllowDependentFunctions) =>
+ val formals1 = if (dropLast == 0) mt.paramTypes else mt.paramTypes dropRight dropLast
defn.FunctionOf(
formals1 mapConserve (_.underlyingIfRepeated(mt.isJava)), mt.resultType, mt.isImplicit && !ctx.erasedTypes)
}
@@ -2102,7 +2102,7 @@ object Types {
}
object RefinedType {
- def make(parent: Type, names: List[Name], infos: List[Type])(implicit ctx: Context): Type =
+ @tailrec def make(parent: Type, names: List[Name], infos: List[Type])(implicit ctx: Context): Type =
if (names.isEmpty) parent
else make(RefinedType(parent, names.head, infos.head), names.tail, infos.tail)
@@ -2313,14 +2313,16 @@ object Types {
trait MethodOrPoly extends MethodicType
- abstract case class MethodType(paramNames: List[TermName], paramTypes: List[Type])
- (resultTypeExp: MethodType => Type)
+ abstract case class MethodType(paramNames: List[TermName])(
+ paramTypesExp: MethodType => List[Type],
+ resultTypeExp: MethodType => Type)
extends CachedGroundType with BindingType with TermType with MethodOrPoly with NarrowCached { thisMethodType =>
import MethodType._
def isJava = false
def isImplicit = false
+ val paramTypes = paramTypesExp(this)
private[core] val resType = resultTypeExp(this)
assert(resType.exists)
@@ -2330,7 +2332,7 @@ object Types {
def apply(tp: Type) = tp match {
case tp @ TypeRef(pre, name) =>
tp.info match {
- case TypeAlias(alias) if depStatus(pre) == TrueDeps => apply(alias)
+ case TypeAlias(alias) if depStatus(NoDeps, pre) == TrueDeps => apply(alias)
case _ => mapOver(tp)
}
case _ =>
@@ -2342,8 +2344,9 @@ object Types {
else resType
var myDependencyStatus: DependencyStatus = Unknown
+ var myParamDependencyStatus: DependencyStatus = Unknown
- private def depStatus(tp: Type)(implicit ctx: Context): DependencyStatus = {
+ private def depStatus(initial: DependencyStatus, tp: Type)(implicit ctx: Context): DependencyStatus = {
def combine(x: DependencyStatus, y: DependencyStatus) = {
val status = (x & StatusMask) max (y & StatusMask)
val provisional = (x | y) & Provisional
@@ -2367,7 +2370,7 @@ object Types {
case _ => foldOver(status, tp)
}
}
- depStatusAcc(NoDeps, tp)
+ depStatusAcc(initial, tp)
}
/** The dependency status of this method. Some examples:
@@ -2381,17 +2384,36 @@ object Types {
private def dependencyStatus(implicit ctx: Context): DependencyStatus = {
if (myDependencyStatus != Unknown) myDependencyStatus
else {
- val result = depStatus(resType)
+ val result = depStatus(NoDeps, resType)
if ((result & Provisional) == 0) myDependencyStatus = result
(result & StatusMask).toByte
}
}
+ /** The parameter dependency status of this method. Analogous to `dependencyStatus`,
+ * but tracking dependencies in same parameter list.
+ */
+ private def paramDependencyStatus(implicit ctx: Context): DependencyStatus = {
+ if (myParamDependencyStatus != Unknown) myParamDependencyStatus
+ else {
+ val result =
+ if (paramTypes.isEmpty) NoDeps
+ else (NoDeps /: paramTypes.tail)(depStatus(_, _))
+ if ((result & Provisional) == 0) myParamDependencyStatus = result
+ (result & StatusMask).toByte
+ }
+ }
+
/** Does result type contain references to parameters of this method type,
* which cannot be eliminated by de-aliasing?
*/
def isDependent(implicit ctx: Context): Boolean = dependencyStatus == TrueDeps
+ /** Does one of the parameter types contain references to earlier parameters
+ * of this method type which cannot be eliminated by de-aliasing?
+ */
+ def isParamDependent(implicit ctx: Context): Boolean = paramDependencyStatus == TrueDeps
+
protected def computeSignature(implicit ctx: Context): Signature =
resultSignature.prepend(paramTypes, isJava)
@@ -2400,10 +2422,11 @@ object Types {
resType: Type = this.resType)(implicit ctx: Context) =
if ((paramNames eq this.paramNames) && (paramTypes eq this.paramTypes) && (resType eq this.resType)) this
else {
+ val paramTypesFn = (x: MethodType) => paramTypes.map(_.subst(this, x))
val resTypeFn = (x: MethodType) => resType.subst(this, x)
- if (isJava) JavaMethodType(paramNames, paramTypes)(resTypeFn)
- else if (isImplicit) ImplicitMethodType(paramNames, paramTypes)(resTypeFn)
- else MethodType(paramNames, paramTypes)(resTypeFn)
+ if (isJava) JavaMethodType(paramNames)(paramTypesFn, resTypeFn)
+ else if (isImplicit) ImplicitMethodType(paramNames)(paramTypesFn, resTypeFn)
+ else MethodType(paramNames)(paramTypesFn, resTypeFn)
}
def instantiate(argTypes: => List[Type])(implicit ctx: Context): Type =
@@ -2425,21 +2448,21 @@ object Types {
override def toString = s"$prefixString($paramNames, $paramTypes, $resType)"
}
- final class CachedMethodType(paramNames: List[TermName], paramTypes: List[Type])(resultTypeExp: MethodType => Type)
- extends MethodType(paramNames, paramTypes)(resultTypeExp) {
+ final class CachedMethodType(paramNames: List[TermName])(paramTypesExp: MethodType => List[Type], resultTypeExp: MethodType => Type)
+ extends MethodType(paramNames)(paramTypesExp, resultTypeExp) {
override def equals(that: Any) = super.equals(that) && that.isInstanceOf[CachedMethodType]
}
- final class JavaMethodType(paramNames: List[TermName], paramTypes: List[Type])(resultTypeExp: MethodType => Type)
- extends MethodType(paramNames, paramTypes)(resultTypeExp) {
+ final class JavaMethodType(paramNames: List[TermName])(paramTypesExp: MethodType => List[Type], resultTypeExp: MethodType => Type)
+ extends MethodType(paramNames)(paramTypesExp, resultTypeExp) {
override def isJava = true
override def equals(that: Any) = super.equals(that) && that.isInstanceOf[JavaMethodType]
override def computeHash = addDelta(super.computeHash, 1)
override protected def prefixString = "JavaMethodType"
}
- final class ImplicitMethodType(paramNames: List[TermName], paramTypes: List[Type])(resultTypeExp: MethodType => Type)
- extends MethodType(paramNames, paramTypes)(resultTypeExp) {
+ final class ImplicitMethodType(paramNames: List[TermName])(paramTypesExp: MethodType => List[Type], resultTypeExp: MethodType => Type)
+ extends MethodType(paramNames)(paramTypesExp, resultTypeExp) {
override def isImplicit = true
override def equals(that: Any) = super.equals(that) && that.isInstanceOf[ImplicitMethodType]
override def computeHash = addDelta(super.computeHash, 2)
@@ -2447,11 +2470,11 @@ object Types {
}
abstract class MethodTypeCompanion {
- def apply(paramNames: List[TermName], paramTypes: List[Type])(resultTypeExp: MethodType => Type)(implicit ctx: Context): MethodType
+ def apply(paramNames: List[TermName])(paramTypesExp: MethodType => List[Type], resultTypeExp: MethodType => Type)(implicit ctx: Context): MethodType
def apply(paramNames: List[TermName], paramTypes: List[Type], resultType: Type)(implicit ctx: Context): MethodType =
- apply(paramNames, paramTypes)(_ => resultType)
+ apply(paramNames)(_ => paramTypes, _ => resultType)
def apply(paramTypes: List[Type])(resultTypeExp: MethodType => Type)(implicit ctx: Context): MethodType =
- apply(nme.syntheticParamNames(paramTypes.length), paramTypes)(resultTypeExp)
+ apply(nme.syntheticParamNames(paramTypes.length))(_ => paramTypes, resultTypeExp)
def apply(paramTypes: List[Type], resultType: Type)(implicit ctx: Context): MethodType =
apply(nme.syntheticParamNames(paramTypes.length), paramTypes, resultType)
@@ -2474,19 +2497,31 @@ object Types {
case _: ExprType => tp
case _ => AnnotatedType(tp, Annotation(defn.InlineParamAnnot))
}
+ def integrate(tp: Type, mt: MethodType) =
+ tp.subst(params, (0 until params.length).toList.map(MethodParam(mt, _)))
def paramInfo(param: Symbol): Type = {
val paramType = translateRepeated(param.info)
if (param.is(Inline)) translateInline(paramType) else paramType
}
- def transformResult(mt: MethodType) =
- resultType.subst(params, (0 until params.length).toList map (MethodParam(mt, _)))
- apply(params map (_.name.asTermName), params map paramInfo)(transformResult _)
+ apply(params.map(_.name.asTermName))(
+ mt => params.map(param => integrate(paramInfo(param), mt)),
+ mt => integrate(resultType, mt))
+ }
+
+ def checkValid(mt: MethodType)(implicit ctx: Context): mt.type = {
+ if (Config.checkMethodTypes)
+ for ((paramType, idx) <- mt.paramTypes.zipWithIndex)
+ paramType.foreachPart {
+ case MethodParam(`mt`, j) => assert(j < idx, mt)
+ case _ =>
+ }
+ mt
}
}
object MethodType extends MethodTypeCompanion {
- def apply(paramNames: List[TermName], paramTypes: List[Type])(resultTypeExp: MethodType => Type)(implicit ctx: Context) =
- unique(new CachedMethodType(paramNames, paramTypes)(resultTypeExp))
+ def apply(paramNames: List[TermName])(paramTypesExp: MethodType => List[Type], resultTypeExp: MethodType => Type)(implicit ctx: Context): MethodType =
+ checkValid(unique(new CachedMethodType(paramNames)(paramTypesExp, resultTypeExp)))
private type DependencyStatus = Byte
private final val Unknown: DependencyStatus = 0 // not yet computed
@@ -2498,13 +2533,19 @@ object Types {
}
object JavaMethodType extends MethodTypeCompanion {
- def apply(paramNames: List[TermName], paramTypes: List[Type])(resultTypeExp: MethodType => Type)(implicit ctx: Context) =
- unique(new JavaMethodType(paramNames, paramTypes)(resultTypeExp))
+ def apply(paramNames: List[TermName])(paramTypesExp: MethodType => List[Type], resultTypeExp: MethodType => Type)(implicit ctx: Context): MethodType =
+ unique(new JavaMethodType(paramNames)(paramTypesExp, resultTypeExp))
}
object ImplicitMethodType extends MethodTypeCompanion {
- def apply(paramNames: List[TermName], paramTypes: List[Type])(resultTypeExp: MethodType => Type)(implicit ctx: Context) =
- unique(new ImplicitMethodType(paramNames, paramTypes)(resultTypeExp))
+ def apply(paramNames: List[TermName])(paramTypesExp: MethodType => List[Type], resultTypeExp: MethodType => Type)(implicit ctx: Context): MethodType =
+ checkValid(unique(new ImplicitMethodType(paramNames)(paramTypesExp, resultTypeExp)))
+ }
+
+ /** A ternary extractor for MethodType */
+ object MethodTpe {
+ def unapply(mt: MethodType)(implicit ctx: Context) =
+ Some((mt.paramNames, mt.paramTypes, mt.resultType))
}
/** A by-name parameter type of the form `=> T`, or the type of a method with no parameter list. */
@@ -2548,11 +2589,6 @@ object Types {
case _ => false
}
- /** Is this polytype a higher-kinded type lambda as opposed to a polymorphic?
- * method type? Only type lambdas get created with variances, that's how we can tell.
- */
- def isTypeLambda: Boolean = variances.nonEmpty
-
/** PolyParam references to all type parameters of this type */
lazy val paramRefs: List[PolyParam] = paramNames.indices.toList.map(PolyParam(this, _))
@@ -2929,20 +2965,8 @@ object Types {
* instantiation can be a singleton type only if the upper bound
* is also a singleton type.
*/
- def instantiate(fromBelow: Boolean)(implicit ctx: Context): Type = {
- val inst = ctx.typeComparer.instanceType(origin, fromBelow)
- if (ctx.typerState.isGlobalCommittable)
- inst match {
- case inst: PolyParam =>
- assert(inst.binder.isTypeLambda, i"bad inst $this := $inst, constr = ${ctx.typerState.constraint}")
- // If this fails, you might want to turn on Config.debugCheckConstraintsClosed
- // to help find the root of the problem.
- // Note: Parameters of type lambdas are excluded from the assertion because
- // they might arise from ill-kinded code. See #1652
- case _ =>
- }
- instantiateWith(inst)
- }
+ def instantiate(fromBelow: Boolean)(implicit ctx: Context): Type =
+ instantiateWith(ctx.typeComparer.instanceType(origin, fromBelow))
/** Unwrap to instance (if instantiated) or origin (if not), until result
* is no longer a TypeVar
@@ -3329,6 +3353,8 @@ object Types {
zeroParamClass(tp.underlying)
case tp: TypeVar =>
zeroParamClass(tp.underlying)
+ case tp: HKApply =>
+ zeroParamClass(tp.superType)
case _ =>
NoType
}
@@ -3659,9 +3685,9 @@ object Types {
this(y, hi)
}
- case tp @ MethodType(pnames, ptypes) =>
+ case tp: MethodType =>
variance = -variance
- val y = foldOver(x, ptypes)
+ val y = foldOver(x, tp.paramTypes)
variance = -variance
this(y, tp.resultType)
@@ -3684,7 +3710,7 @@ object Types {
this(x, prefix)
case tp @ HKApply(tycon, args) =>
- def foldArgs(x: T, tparams: List[TypeParamInfo], args: List[Type]): T =
+ @tailrec def foldArgs(x: T, tparams: List[TypeParamInfo], args: List[Type]): T =
if (args.isEmpty) {
assert(tparams.isEmpty)
x
@@ -3727,7 +3753,7 @@ object Types {
case _ => x
}
- final def foldOver(x: T, ts: List[Type]): T = ts match {
+ @tailrec final def foldOver(x: T, ts: List[Type]): T = ts match {
case t :: ts1 => foldOver(apply(x, t), ts1)
case nil => x
}
diff --git a/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala
index 36d478c6d..bc140c26b 100644
--- a/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala
+++ b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala
@@ -198,8 +198,8 @@ class ClassfileParser(
*/
def stripOuterParamFromConstructor() = innerClasses.get(currentClassName) match {
case Some(entry) if !isStatic(entry.jflags) =>
- val mt @ MethodType(paramnames, paramtypes) = denot.info
- denot.info = mt.derivedMethodType(paramnames.tail, paramtypes.tail, mt.resultType)
+ val mt @ MethodTpe(paramNames, paramTypes, resultType) = denot.info
+ denot.info = mt.derivedMethodType(paramNames.tail, paramTypes.tail, resultType)
case _ =>
}
@@ -207,9 +207,9 @@ class ClassfileParser(
* and make constructor type polymorphic in the type parameters of the class
*/
def normalizeConstructorInfo() = {
- val mt @ MethodType(paramnames, paramtypes) = denot.info
+ val mt @ MethodType(paramNames) = denot.info
val rt = classRoot.typeRef appliedTo (classRoot.typeParams map (_.typeRef))
- denot.info = mt.derivedMethodType(paramnames, paramtypes, rt)
+ denot.info = mt.derivedMethodType(paramNames, mt.paramTypes, rt)
addConstructorTypeParams(denot)
}
@@ -339,7 +339,7 @@ class ClassfileParser(
}
index += 1
val restype = sig2type(tparams, skiptvs)
- JavaMethodType(paramnames.toList, paramtypes.toList)(_ => restype)
+ JavaMethodType(paramnames.toList, paramtypes.toList, restype)
case 'T' =>
val n = subName(';'.==).toTypeName
index += 1
diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
index fdb8a97ae..a9ea49ad1 100644
--- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
+++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
@@ -278,8 +278,9 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, posUnpickle
result
case METHODtype =>
val (names, paramReader) = readNamesSkipParams
- val result = MethodType(names.map(_.toTermName), paramReader.readParamTypes[Type](end))(
- mt => registeringType(mt, readType()))
+ val result = MethodType(names.map(_.toTermName))(
+ mt => registeringType(mt, paramReader.readParamTypes[Type](end)),
+ mt => readType())
goto(end)
result
case PARAMtype =>
diff --git a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala
index faf01b177..688a2d007 100644
--- a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala
+++ b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala
@@ -55,8 +55,8 @@ object Scala2Unpickler {
* to `RepeatedParamClass` types.
*/
def arrayToRepeated(tp: Type)(implicit ctx: Context): Type = tp match {
- case tp @ MethodType(paramNames, paramTypes) =>
- val lastArg = paramTypes.last
+ case tp: MethodType =>
+ val lastArg = tp.paramTypes.last
assert(lastArg isRef defn.ArrayClass)
val elemtp0 :: Nil = lastArg.baseArgInfos(defn.ArrayClass)
val elemtp = elemtp0 match {
@@ -66,8 +66,8 @@ object Scala2Unpickler {
elemtp0
}
tp.derivedMethodType(
- paramNames,
- paramTypes.init :+ defn.RepeatedParamType.appliedTo(elemtp),
+ tp.paramNames,
+ tp.paramTypes.init :+ defn.RepeatedParamType.appliedTo(elemtp),
tp.resultType)
case tp: PolyType =>
tp.derivedPolyType(tp.paramNames, tp.paramBounds, arrayToRepeated(tp.resultType))
diff --git a/compiler/src/dotty/tools/dotc/rewrite/Rewrites.scala b/compiler/src/dotty/tools/dotc/rewrite/Rewrites.scala
index c42c808fe..909a145d1 100644
--- a/compiler/src/dotty/tools/dotc/rewrite/Rewrites.scala
+++ b/compiler/src/dotty/tools/dotc/rewrite/Rewrites.scala
@@ -5,6 +5,7 @@ import util.{SourceFile, Positions}
import Positions.Position
import core.Contexts.{Context, FreshContext}
import collection.mutable
+import scala.annotation.tailrec
/** Handles rewriting of Scala2 files to Dotty */
object Rewrites {
@@ -29,7 +30,7 @@ object Rewrites {
p2
}
val ds = new Array[Char](cs.length + delta)
- def loop(ps: List[Patch], inIdx: Int, outIdx: Int): Unit = {
+ @tailrec def loop(ps: List[Patch], inIdx: Int, outIdx: Int): Unit = {
def copy(upTo: Int): Int = {
val untouched = upTo - inIdx
Array.copy(cs, inIdx, ds, outIdx, untouched)
diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala
index 599522b74..43202ef87 100644
--- a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala
+++ b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala
@@ -284,7 +284,7 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder
case pt: PolyType =>
assert(start == 0)
paramLists(pt.resultType)
- case mt @ MethodType(pnames, ptypes) =>
+ case mt @ MethodTpe(pnames, ptypes, restpe) =>
// TODO: We shouldn't have to work so hard to find the default parameters
// of a method, Dotty should expose a convenience method for that, see #1143
val defaults =
@@ -300,7 +300,7 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder
val params = (pnames, ptypes, defaults).zipped.map((pname, ptype, isDefault) =>
new api.MethodParameter(pname.toString, apiType(ptype),
isDefault, api.ParameterModifier.Plain))
- new api.ParameterList(params.toArray, mt.isImplicit) :: paramLists(mt.resultType, params.length)
+ new api.ParameterList(params.toArray, mt.isImplicit) :: paramLists(restpe, params.length)
case _ =>
Nil
}
diff --git a/compiler/src/dotty/tools/dotc/transform/CollectEntryPoints.scala b/compiler/src/dotty/tools/dotc/transform/CollectEntryPoints.scala
index 331fce46a..9f1e42e31 100644
--- a/compiler/src/dotty/tools/dotc/transform/CollectEntryPoints.scala
+++ b/compiler/src/dotty/tools/dotc/transform/CollectEntryPoints.scala
@@ -64,7 +64,7 @@ class CollectEntryPoints extends MiniPhaseTransform {
val hasApproximate = possibles exists {
m =>
m.info match {
- case MethodType(_, p :: Nil) =>
+ case MethodTpe(_, p :: Nil, _) =>
p.typeSymbol == defn.ArrayClass
case _ => false
}
@@ -87,8 +87,8 @@ class CollectEntryPoints extends MiniPhaseTransform {
m.symbol.info match {
case t: PolyType =>
fail("main methods cannot be generic.")
- case t@MethodType(paramNames, paramTypes) =>
- if (t.resultType :: paramTypes exists (_.typeSymbol.isAbstractType))
+ case t: MethodType =>
+ if (t.resultType :: t.paramTypes exists (_.typeSymbol.isAbstractType))
fail("main methods cannot refer to type parameters or abstract types.", m.symbol.pos)
else
javaPlatform.isJavaMainMethod(m.symbol) || fail("main method must have exact signature (Array[String])Unit", m.symbol.pos)
diff --git a/compiler/src/dotty/tools/dotc/transform/ElimByName.scala b/compiler/src/dotty/tools/dotc/transform/ElimByName.scala
index 0e187fc2e..59da78590 100644
--- a/compiler/src/dotty/tools/dotc/transform/ElimByName.scala
+++ b/compiler/src/dotty/tools/dotc/transform/ElimByName.scala
@@ -92,8 +92,8 @@ class ElimByName extends MiniPhaseTransform with InfoTransformer { thisTransform
arg
}
- val MethodType(_, formals) = tree.fun.tpe.widen
- val args1 = tree.args.zipWithConserve(formals)(transformArg)
+ val mt @ MethodType(_) = tree.fun.tpe.widen
+ val args1 = tree.args.zipWithConserve(mt.paramTypes)(transformArg)
cpy.Apply(tree)(tree.fun, args1)
}
diff --git a/compiler/src/dotty/tools/dotc/transform/ElimRepeated.scala b/compiler/src/dotty/tools/dotc/transform/ElimRepeated.scala
index d955628e3..ae3259509 100644
--- a/compiler/src/dotty/tools/dotc/transform/ElimRepeated.scala
+++ b/compiler/src/dotty/tools/dotc/transform/ElimRepeated.scala
@@ -48,8 +48,8 @@ class ElimRepeated extends MiniPhaseTransform with InfoTransformer with Annotati
private def overridesJava(sym: Symbol)(implicit ctx: Context) = sym.allOverriddenSymbols.exists(_ is JavaDefined)
private def elimRepeated(tp: Type)(implicit ctx: Context): Type = tp.stripTypeVar match {
- case tp @ MethodType(paramNames, paramTypes) =>
- val resultType1 = elimRepeated(tp.resultType)
+ case tp @ MethodTpe(paramNames, paramTypes, resultType) =>
+ val resultType1 = elimRepeated(resultType)
val paramTypes1 =
if (paramTypes.nonEmpty && paramTypes.last.isRepeatedParam) {
val last = paramTypes.last.underlyingIfRepeated(tp.isJava)
diff --git a/compiler/src/dotty/tools/dotc/transform/Erasure.scala b/compiler/src/dotty/tools/dotc/transform/Erasure.scala
index 3857b405f..f9c7a8e1e 100644
--- a/compiler/src/dotty/tools/dotc/transform/Erasure.scala
+++ b/compiler/src/dotty/tools/dotc/transform/Erasure.scala
@@ -40,8 +40,8 @@ class Erasure extends Phase with DenotTransformer { thisTransformer =>
def isCompacted(sym: Symbol) =
sym.isAnonymousFunction && {
sym.info(ctx.withPhase(ctx.phase.next)) match {
- case MethodType(nme.ALLARGS :: Nil, _) => true
- case _ => false
+ case MethodType(nme.ALLARGS :: Nil) => true
+ case _ => false
}
}
@@ -269,7 +269,7 @@ object Erasure extends TypeTestsCasts{
def adaptToType(tree: Tree, pt: Type)(implicit ctx: Context): Tree =
if (pt.isInstanceOf[FunProto]) tree
else tree.tpe.widen match {
- case MethodType(Nil, _) if tree.isTerm =>
+ case MethodType(Nil) if tree.isTerm =>
adaptToType(tree.appliedToNone, pt)
case tpw =>
if (pt.isInstanceOf[ProtoType] || tree.tpe <:< pt)
@@ -697,9 +697,10 @@ object Erasure extends TypeTestsCasts{
val rhs = paramss.foldLeft(sel)((fun, vparams) =>
fun.tpe.widen match {
- case MethodType(names, types) => Apply(fun, (vparams, types).zipped.map(adapt(_, _, untpd.EmptyTree)))
- case a => error(s"can not resolve apply type $a")
-
+ case mt: MethodType =>
+ Apply(fun, (vparams, mt.paramTypes).zipped.map(adapt(_, _, untpd.EmptyTree)))
+ case a =>
+ error(s"can not resolve apply type $a")
})
adapt(rhs, resultType)
})
diff --git a/compiler/src/dotty/tools/dotc/transform/ExpandSAMs.scala b/compiler/src/dotty/tools/dotc/transform/ExpandSAMs.scala
index 91399f91a..7b15b7e54 100644
--- a/compiler/src/dotty/tools/dotc/transform/ExpandSAMs.scala
+++ b/compiler/src/dotty/tools/dotc/transform/ExpandSAMs.scala
@@ -53,7 +53,7 @@ class ExpandSAMs extends MiniPhaseTransform { thisTransformer =>
val applyRhs: Tree = applyDef.rhs
val applyFn = applyDef.symbol.asTerm
- val MethodType(paramNames, paramTypes) = applyFn.info
+ val MethodTpe(paramNames, paramTypes, _) = applyFn.info
val isDefinedAtFn = applyFn.copy(
name = nme.isDefinedAt,
flags = Synthetic | Method,
diff --git a/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala b/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala
index d75c32fcc..f17808e62 100644
--- a/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala
+++ b/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala
@@ -16,7 +16,9 @@ import SymUtils._
import dotty.tools.dotc.ast.tpd
import dotty.tools.dotc.core.Phases.Phase
import util.Property
+
import collection.mutable
+import scala.annotation.tailrec
/** This phase adds outer accessors to classes and traits that need them.
* Compared to Scala 2.x, it tries to minimize the set of classes
@@ -328,9 +330,9 @@ object ExplicitOuter {
/** If `cls` has an outer parameter add one to the method type `tp`. */
def addParam(cls: ClassSymbol, tp: Type): Type =
if (hasOuterParam(cls)) {
- val mt @ MethodType(pnames, ptypes) = tp
+ val mt @ MethodTpe(pnames, ptypes, restpe) = tp
mt.derivedMethodType(
- nme.OUTER :: pnames, cls.owner.enclosingClass.typeRef :: ptypes, mt.resultType)
+ nme.OUTER :: pnames, cls.owner.enclosingClass.typeRef :: ptypes, restpe)
} else tp
/** If function in an apply node is a constructor that needs to be passed an
@@ -367,7 +369,7 @@ object ExplicitOuter {
def path(start: Tree = This(ctx.owner.lexicallyEnclosingClass.asClass),
toCls: Symbol = NoSymbol,
count: Int = -1): Tree = try {
- def loop(tree: Tree, count: Int): Tree = {
+ @tailrec def loop(tree: Tree, count: Int): Tree = {
val treeCls = tree.tpe.widen.classSymbol
val outerAccessorCtx = ctx.withPhaseNoLater(ctx.lambdaLiftPhase) // lambdalift mangles local class names, which means we cannot reliably find outer acessors anymore
ctx.log(i"outer to $toCls of $tree: ${tree.tpe}, looking for ${outerAccName(treeCls.asClass)(outerAccessorCtx)} in $treeCls")
@@ -389,7 +391,7 @@ object ExplicitOuter {
/** The outer parameter definition of a constructor if it needs one */
def paramDefs(constr: Symbol): List[ValDef] =
if (constr.isConstructor && hasOuterParam(constr.owner.asClass)) {
- val MethodType(outerName :: _, outerType :: _) = constr.info
+ val MethodTpe(outerName :: _, outerType :: _, _) = constr.info
val outerSym = ctx.newSymbol(constr, outerName, Param, outerType)
ValDef(outerSym) :: Nil
}
diff --git a/compiler/src/dotty/tools/dotc/transform/FirstTransform.scala b/compiler/src/dotty/tools/dotc/transform/FirstTransform.scala
index 597146514..8328e43de 100644
--- a/compiler/src/dotty/tools/dotc/transform/FirstTransform.scala
+++ b/compiler/src/dotty/tools/dotc/transform/FirstTransform.scala
@@ -29,8 +29,11 @@ import StdNames._
* - eliminates some kinds of trees: Imports, NamedArgs
* - stubs out native methods
* - eliminates self tree in Template and self symbol in ClassInfo
- * - collapsess all type trees to trees of class TypeTree
+ * - collapses all type trees to trees of class TypeTree
* - converts idempotent expressions with constant types
+ * - drops branches of ifs using the rules
+ * if (true) A else B --> A
+ * if (false) A else B --> B
*/
class FirstTransform extends MiniPhaseTransform with InfoTransformer with AnnotationTransformer { thisTransformer =>
import ast.tpd._
@@ -148,7 +151,7 @@ class FirstTransform extends MiniPhaseTransform with InfoTransformer with Annota
override def transformTemplate(impl: Template)(implicit ctx: Context, info: TransformerInfo): Tree = {
cpy.Template(impl)(self = EmptyValDef)
}
-
+
override def transformDefDef(ddef: DefDef)(implicit ctx: Context, info: TransformerInfo) = {
if (ddef.symbol.hasAnnotation(defn.NativeAnnot)) {
ddef.symbol.resetFlag(Deferred)
@@ -168,13 +171,13 @@ class FirstTransform extends MiniPhaseTransform with InfoTransformer with Annota
}
override def transformIdent(tree: Ident)(implicit ctx: Context, info: TransformerInfo) =
- if (tree.isType) TypeTree(tree.tpe).withPos(tree.pos)
+ if (tree.isType) TypeTree(tree.tpe).withPos(tree.pos)
else constToLiteral(tree)
override def transformSelect(tree: Select)(implicit ctx: Context, info: TransformerInfo) =
- if (tree.isType) TypeTree(tree.tpe).withPos(tree.pos)
+ if (tree.isType) TypeTree(tree.tpe).withPos(tree.pos)
else constToLiteral(tree)
-
+
override def transformTypeApply(tree: TypeApply)(implicit ctx: Context, info: TransformerInfo) =
constToLiteral(tree)
@@ -183,10 +186,16 @@ class FirstTransform extends MiniPhaseTransform with InfoTransformer with Annota
override def transformTyped(tree: Typed)(implicit ctx: Context, info: TransformerInfo) =
constToLiteral(tree)
-
+
override def transformBlock(tree: Block)(implicit ctx: Context, info: TransformerInfo) =
constToLiteral(tree)
+ override def transformIf(tree: If)(implicit ctx: Context, info: TransformerInfo) =
+ tree.cond match {
+ case Literal(Constant(c: Boolean)) => if (c) tree.thenp else tree.elsep
+ case _ => tree
+ }
+
// invariants: all modules have companion objects
// all types are TypeTrees
// all this types are explicit
diff --git a/compiler/src/dotty/tools/dotc/transform/FullParameterization.scala b/compiler/src/dotty/tools/dotc/transform/FullParameterization.scala
index 5609817d8..0cb453b4c 100644
--- a/compiler/src/dotty/tools/dotc/transform/FullParameterization.scala
+++ b/compiler/src/dotty/tools/dotc/transform/FullParameterization.scala
@@ -105,8 +105,9 @@ trait FullParameterization {
def resultType(mapClassParams: Type => Type) = {
val thisParamType = mapClassParams(clazz.classInfo.selfType)
val firstArgType = if (liftThisType) thisParamType & clazz.thisType else thisParamType
- MethodType(nme.SELF :: Nil, firstArgType :: Nil)(mt =>
- mapClassParams(origResult).substThisUnlessStatic(clazz, MethodParam(mt, 0)))
+ MethodType(nme.SELF :: Nil)(
+ mt => firstArgType :: Nil,
+ mt => mapClassParams(origResult).substThisUnlessStatic(clazz, MethodParam(mt, 0)))
}
/** Replace class type parameters by the added type parameters of the polytype `pt` */
@@ -252,10 +253,10 @@ object FullParameterization {
def memberSignature(info: Type)(implicit ctx: Context): Signature = info match {
case info: PolyType =>
memberSignature(info.resultType)
- case info @ MethodType(nme.SELF :: Nil, _) =>
- info.resultType.ensureMethodic.signature
- case info @ MethodType(nme.SELF :: otherNames, thisType :: otherTypes) =>
- info.derivedMethodType(otherNames, otherTypes, info.resultType).signature
+ case MethodTpe(nme.SELF :: Nil, _, restpe) =>
+ restpe.ensureMethodic.signature
+ case info @ MethodTpe(nme.SELF :: otherNames, thisType :: otherTypes, restpe) =>
+ info.derivedMethodType(otherNames, otherTypes, restpe).signature
case _ =>
Signature.NotAMethod
}
diff --git a/compiler/src/dotty/tools/dotc/transform/LambdaLift.scala b/compiler/src/dotty/tools/dotc/transform/LambdaLift.scala
index b603a53dc..7578b57f1 100644
--- a/compiler/src/dotty/tools/dotc/transform/LambdaLift.scala
+++ b/compiler/src/dotty/tools/dotc/transform/LambdaLift.scala
@@ -352,12 +352,12 @@ class LambdaLift extends MiniPhase with IdentityDenotTransformer { thisTransform
}
private def liftedInfo(local: Symbol)(implicit ctx: Context): Type = local.info match {
- case mt @ MethodType(pnames, ptypes) =>
+ case MethodTpe(pnames, ptypes, restpe) =>
val ps = proxies(local)
MethodType(
ps.map(_.name.asTermName) ++ pnames,
ps.map(_.info) ++ ptypes,
- mt.resultType)
+ restpe)
case info => info
}
diff --git a/compiler/src/dotty/tools/dotc/transform/LazyVals.scala b/compiler/src/dotty/tools/dotc/transform/LazyVals.scala
index a6ac71286..2035fb04b 100644
--- a/compiler/src/dotty/tools/dotc/transform/LazyVals.scala
+++ b/compiler/src/dotty/tools/dotc/transform/LazyVals.scala
@@ -139,7 +139,7 @@ class LazyVals extends MiniPhaseTransform with IdentityDenotTransformer {
val holderSymbol = ctx.newSymbol(x.symbol.owner, holderName, containerFlags, holderImpl.typeRef, coord = x.pos)
val initSymbol = ctx.newSymbol(x.symbol.owner, initName, initFlags, MethodType(Nil, tpe), coord = x.pos)
- val result = ref(holderSymbol).select(lazyNme.value)
+ val result = ref(holderSymbol).select(lazyNme.value).withPos(x.pos)
val flag = ref(holderSymbol).select(lazyNme.initialized)
val initer = valueInitter.changeOwnerAfter(x.symbol, initSymbol, this)
val initBody =
diff --git a/compiler/src/dotty/tools/dotc/transform/ParamForwarding.scala b/compiler/src/dotty/tools/dotc/transform/ParamForwarding.scala
index a72e10681..859ac8b06 100644
--- a/compiler/src/dotty/tools/dotc/transform/ParamForwarding.scala
+++ b/compiler/src/dotty/tools/dotc/transform/ParamForwarding.scala
@@ -27,7 +27,7 @@ class ParamForwarding(thisTransformer: DenotTransformer) {
val (superArgs, superParamNames) = impl.parents match {
case superCall @ Apply(fn, args) :: _ =>
fn.tpe.widen match {
- case MethodType(paramNames, _) => (args, paramNames)
+ case MethodType(paramNames) => (args, paramNames)
case _ => (Nil, Nil)
}
case _ => (Nil, Nil)
diff --git a/compiler/src/dotty/tools/dotc/transform/SymUtils.scala b/compiler/src/dotty/tools/dotc/transform/SymUtils.scala
index 05305575e..105f54d3a 100644
--- a/compiler/src/dotty/tools/dotc/transform/SymUtils.scala
+++ b/compiler/src/dotty/tools/dotc/transform/SymUtils.scala
@@ -12,7 +12,9 @@ import StdNames._
import NameOps._
import Flags._
import Annotations._
+
import language.implicitConversions
+import scala.annotation.tailrec
object SymUtils {
implicit def decorateSymbol(sym: Symbol): SymUtils = new SymUtils(sym)
@@ -59,14 +61,14 @@ class SymUtils(val self: Symbol) extends AnyVal {
}
/** The closest enclosing method or class of this symbol */
- final def enclosingMethodOrClass(implicit ctx: Context): Symbol =
+ @tailrec final def enclosingMethodOrClass(implicit ctx: Context): Symbol =
if (self.is(Method, butNot = Label) || self.isClass) self
else if (self.exists) self.owner.enclosingMethodOrClass
else NoSymbol
/** Apply symbol/symbol substitution to this symbol */
def subst(from: List[Symbol], to: List[Symbol]): Symbol = {
- def loop(from: List[Symbol], to: List[Symbol]): Symbol =
+ @tailrec def loop(from: List[Symbol], to: List[Symbol]): Symbol =
if (from.isEmpty) self
else if (self eq from.head) to.head
else loop(from.tail, to.tail)
diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala
index a65ef00cc..5dcf16b62 100644
--- a/compiler/src/dotty/tools/dotc/typer/Applications.scala
+++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala
@@ -178,6 +178,8 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
*/
protected def normalizedFun: Tree
+ protected def typeOfArg(arg: Arg): Type
+
/** If constructing trees, pull out all parts of the function
* which are not idempotent into separate prefix definitions
*/
@@ -380,8 +382,16 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
if (success) formals match {
case formal :: formals1 =>
- def addTyped(arg: Arg, formal: Type) =
+ /** Add result of typing argument `arg` against parameter type `formal`.
+ * @return A type transformation to apply to all arguments following this one.
+ */
+ def addTyped(arg: Arg, formal: Type): Type => Type = {
addArg(typedArg(arg, formal), formal)
+ if (methodType.isParamDependent)
+ _.substParam(MethodParam(methodType, n), typeOfArg(arg))
+ else
+ identity
+ }
def missingArg(n: Int): Unit = {
val pname = methodType.paramNames(n)
@@ -395,8 +405,10 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
val getter = findDefaultGetter(n + numArgs(normalizedFun))
if (getter.isEmpty) missingArg(n)
else {
- addTyped(treeToArg(spliceMeth(getter withPos normalizedFun.pos, normalizedFun)), formal)
- matchArgs(args1, formals1, n + 1)
+ val substParam = addTyped(
+ treeToArg(spliceMeth(getter withPos normalizedFun.pos, normalizedFun)),
+ formal)
+ matchArgs(args1, formals1.mapconserve(substParam), n + 1)
}
}
@@ -420,8 +432,8 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
case EmptyTree :: args1 =>
tryDefault(n, args1)
case arg :: args1 =>
- addTyped(arg, formal)
- matchArgs(args1, formals1, n + 1)
+ val substParam = addTyped(arg, formal)
+ matchArgs(args1, formals1.mapconserve(substParam), n + 1)
case nil =>
tryDefault(n, args)
}
@@ -477,6 +489,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
def argType(arg: Tree, formal: Type): Type = normalize(arg.tpe, formal)
def treeToArg(arg: Tree): Tree = arg
def isVarArg(arg: Tree): Boolean = tpd.isWildcardStarArg(arg)
+ def typeOfArg(arg: Tree): Type = arg.tpe
def harmonizeArgs(args: List[Tree]) = harmonize(args)
}
@@ -494,6 +507,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
def argType(arg: Type, formal: Type): Type = arg
def treeToArg(arg: Tree): Type = arg.tpe
def isVarArg(arg: Type): Boolean = arg.isRepeatedParam
+ def typeOfArg(arg: Type): Type = arg
def harmonizeArgs(args: List[Type]) = harmonizeTypes(args)
}
@@ -592,6 +606,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
extends TypedApply(app, fun, methRef, proto.args, resultType) {
def typedArg(arg: untpd.Tree, formal: Type): TypedArg = proto.typedArg(arg, formal.widenExpr)
def treeToArg(arg: Tree): untpd.Tree = untpd.TypedSplice(arg)
+ def typeOfArg(arg: untpd.Tree) = proto.typeOfArg(arg)
}
/** Subclass of Application for type checking an Apply node with typed arguments. */
@@ -603,6 +618,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
// not match the abstract method in Application and an abstract class error results.
def typedArg(arg: tpd.Tree, formal: Type): TypedArg = arg
def treeToArg(arg: Tree): Tree = arg
+ def typeOfArg(arg: Tree) = arg.tpe
}
/** If `app` is a `this(...)` constructor call, the this-call argument context,
@@ -1263,7 +1279,8 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
def sizeFits(alt: TermRef, tp: Type): Boolean = tp match {
case tp: PolyType => sizeFits(alt, tp.resultType)
- case MethodType(_, ptypes) =>
+ case tp: MethodType =>
+ val ptypes = tp.paramTypes
val numParams = ptypes.length
def isVarArgs = ptypes.nonEmpty && ptypes.last.isRepeatedParam
def hasDefault = alt.symbol.hasDefaultParams
diff --git a/compiler/src/dotty/tools/dotc/typer/Checking.scala b/compiler/src/dotty/tools/dotc/typer/Checking.scala
index f822f8893..b43391592 100644
--- a/compiler/src/dotty/tools/dotc/typer/Checking.scala
+++ b/compiler/src/dotty/tools/dotc/typer/Checking.scala
@@ -441,7 +441,6 @@ object Checking {
case List(param) =>
if (param.is(Mutable))
ctx.error("value class parameter must not be a var", param.pos)
-
case _ =>
ctx.error("value class needs to have exactly one val parameter", clazz.pos)
}
@@ -625,6 +624,24 @@ trait Checking {
case _ =>
}
}
+
+ /** Check that method parameter types do not reference their own parameter
+ * or later parameters in the same parameter section.
+ */
+ def checkNoForwardDependencies(vparams: List[ValDef])(implicit ctx: Context): Unit = vparams match {
+ case vparam :: vparams1 =>
+ val check = new TreeTraverser {
+ def traverse(tree: Tree)(implicit ctx: Context) = tree match {
+ case id: Ident if vparams.exists(_.symbol == id.symbol) =>
+ ctx.error("illegal forward reference to method parameter", id.pos)
+ case _ =>
+ traverseChildren(tree)
+ }
+ }
+ check.traverse(vparam.tpt)
+ checkNoForwardDependencies(vparams1)
+ case Nil =>
+ }
}
trait NoChecking extends Checking {
@@ -642,4 +659,5 @@ trait NoChecking extends Checking {
override def checkNotSingleton(tpt: Tree, where: String)(implicit ctx: Context): Tree = tpt
override def checkDerivedValueClass(clazz: Symbol, stats: List[Tree])(implicit ctx: Context) = ()
override def checkTraitInheritance(parentSym: Symbol, cls: ClassSymbol, pos: Position)(implicit ctx: Context) = ()
+ override def checkNoForwardDependencies(vparams: List[ValDef])(implicit ctx: Context): Unit = ()
}
diff --git a/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala b/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala
index e7e7ece78..57c1808c9 100644
--- a/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala
+++ b/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala
@@ -59,8 +59,8 @@ object EtaExpansion {
*/
def liftArgs(defs: mutable.ListBuffer[Tree], methRef: Type, args: List[Tree])(implicit ctx: Context) =
methRef.widen match {
- case MethodType(paramNames, paramTypes) =>
- (args, paramNames, paramTypes).zipped map { (arg, name, tp) =>
+ case mt: MethodType =>
+ (args, mt.paramNames, mt.paramTypes).zipped map { (arg, name, tp) =>
if (tp.isInstanceOf[ExprType]) arg
else liftArg(defs, arg, if (name contains '$') "" else name.toString + "$")
}
diff --git a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala
index b588e3ae5..f7dd725c8 100644
--- a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala
+++ b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala
@@ -237,6 +237,12 @@ object ProtoTypes {
typer.adapt(targ, formal, arg)
}
+ /** The type of the argument `arg`.
+ * @pre `arg` has been typed before
+ */
+ def typeOfArg(arg: untpd.Tree)(implicit ctx: Context): Type =
+ myTypedArg(arg).tpe
+
private var myTupled: Type = NoType
/** The same proto-type but with all arguments combined in a single tuple */
diff --git a/compiler/src/dotty/tools/dotc/typer/ReTyper.scala b/compiler/src/dotty/tools/dotc/typer/ReTyper.scala
index 3252ead47..6080c6644 100644
--- a/compiler/src/dotty/tools/dotc/typer/ReTyper.scala
+++ b/compiler/src/dotty/tools/dotc/typer/ReTyper.scala
@@ -85,8 +85,8 @@ class ReTyper extends Typer {
override def encodeName(tree: untpd.NameTree)(implicit ctx: Context) = tree
override def handleUnexpectedFunType(tree: untpd.Apply, fun: Tree)(implicit ctx: Context): Tree = fun.tpe match {
- case mt @ MethodType(_, formals) =>
- val args: List[Tree] = tree.args.zipWithConserve(formals)(typedExpr(_, _)).asInstanceOf[List[Tree]]
+ case mt: MethodType =>
+ val args: List[Tree] = tree.args.zipWithConserve(mt.paramTypes)(typedExpr(_, _)).asInstanceOf[List[Tree]]
assignType(untpd.cpy.Apply(tree)(fun, args), fun, args)
case _ =>
super.handleUnexpectedFunType(tree, fun)
diff --git a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala
index e8ff7d572..d61f5fa68 100644
--- a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala
+++ b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala
@@ -739,11 +739,7 @@ import RefChecks._
*
* 2. It warns about references to symbols labeled deprecated or migration.
- * 3. It performs the following transformations:
- *
- * - if (true) A else B --> A
- * if (false) A else B --> B
- * - macro definitions are eliminated.
+ * 3. It eliminates macro definitions.
*
* 4. It makes members not private where necessary. The following members
* cannot be private in the Java model:
@@ -836,12 +832,6 @@ class RefChecks extends MiniPhase { thisTransformer =>
tree
}
- override def transformIf(tree: If)(implicit ctx: Context, info: TransformerInfo) =
- tree.cond.tpe match {
- case ConstantType(value) => if (value.booleanValue) tree.thenp else tree.elsep
- case _ => tree
- }
-
override def transformNew(tree: New)(implicit ctx: Context, info: TransformerInfo) = {
currentLevel.enterReference(tree.tpe.typeSymbol, tree.pos)
tree
diff --git a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala
index 6bf8dcbbc..6e774e38e 100644
--- a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala
+++ b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala
@@ -315,10 +315,10 @@ trait TypeAssigner {
def assignType(tree: untpd.Apply, fn: Tree, args: List[Tree])(implicit ctx: Context) = {
val ownType = fn.tpe.widen match {
- case fntpe @ MethodType(_, ptypes) =>
- if (sameLength(ptypes, args) || ctx.phase.prev.relaxedTyping) fntpe.instantiate(args.tpes)
+ case fntpe: MethodType =>
+ if (sameLength(fntpe.paramTypes, args) || ctx.phase.prev.relaxedTyping) fntpe.instantiate(args.tpes)
else
- errorType(i"wrong number of arguments for $fntpe: ${fn.tpe}, expected: ${ptypes.length}, found: ${args.length}", tree.pos)
+ errorType(i"wrong number of arguments for $fntpe: ${fn.tpe}, expected: ${fntpe.paramTypes.length}, found: ${args.length}", tree.pos)
case t =>
errorType(i"${err.exprStr(fn)} does not take parameters", tree.pos)
}
diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala
index ccfe218b3..d4a9744e4 100644
--- a/compiler/src/dotty/tools/dotc/typer/Typer.scala
+++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala
@@ -672,8 +672,8 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
// this can type the greatest set of admissible closures.
(pt.dealias.argTypesLo.init, pt.dealias.argTypesHi.last)
case SAMType(meth) =>
- val mt @ MethodType(_, paramTypes) = meth.info
- (paramTypes, mt.resultType)
+ val MethodTpe(_, formals, restpe) = meth.info
+ (formals, restpe)
case _ =>
(List.range(0, defaultArity) map alwaysWildcardType, WildcardType)
}
@@ -1080,6 +1080,13 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
(if (isVarPattern(arg)) desugar.patternVar(arg) else arg, tparam.paramBounds)
else
(arg, WildcardType)
+ if (tpt1.symbol.isClass)
+ tparam match {
+ case tparam: Symbol =>
+ // This is needed to get the test `compileParSetSubset` to work
+ tparam.ensureCompleted()
+ case _ =>
+ }
typed(desugaredArg, argPt)
}
args.zipWithConserve(tparams)(typedArg(_, _)).asInstanceOf[List[Tree]]
@@ -1222,6 +1229,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
completeAnnotations(ddef, sym)
val tparams1 = tparams mapconserve (typed(_).asInstanceOf[TypeDef])
val vparamss1 = vparamss nestedMapconserve (typed(_).asInstanceOf[ValDef])
+ vparamss1.foreach(checkNoForwardDependencies)
if (sym is Implicit) checkImplicitParamsNotSingletons(vparamss1)
var tpt1 = checkSimpleKinded(typedType(tpt))
@@ -1280,10 +1288,10 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
def maybeCall(ref: Tree, psym: Symbol, cinfo: Type): Tree = cinfo match {
case cinfo: PolyType =>
maybeCall(ref, psym, cinfo.resultType)
- case cinfo @ MethodType(Nil, _) if cinfo.resultType.isInstanceOf[ImplicitMethodType] =>
+ case cinfo @ MethodType(Nil) if cinfo.resultType.isInstanceOf[ImplicitMethodType] =>
val icall = New(ref).select(nme.CONSTRUCTOR).appliedToNone
typedExpr(untpd.TypedSplice(icall))(superCtx)
- case cinfo @ MethodType(Nil, _) if !cinfo.resultType.isInstanceOf[MethodType] =>
+ case cinfo @ MethodType(Nil) if !cinfo.resultType.isInstanceOf[MethodType] =>
ref
case cinfo: MethodType =>
if (!ctx.erasedTypes) { // after constructors arguments are passed in super call.
diff --git a/compiler/src/dotty/tools/dotc/typer/Variances.scala b/compiler/src/dotty/tools/dotc/typer/Variances.scala
index 92bd9fd74..5a1745930 100644
--- a/compiler/src/dotty/tools/dotc/typer/Variances.scala
+++ b/compiler/src/dotty/tools/dotc/typer/Variances.scala
@@ -79,8 +79,8 @@ object Variances {
varianceInType(parent)(tparam) & varianceInType(rinfo)(tparam)
case tp: RecType =>
varianceInType(tp.parent)(tparam)
- case tp @ MethodType(_, paramTypes) =>
- flip(varianceInTypes(paramTypes)(tparam)) & varianceInType(tp.resultType)(tparam)
+ case tp: MethodType =>
+ flip(varianceInTypes(tp.paramTypes)(tparam)) & varianceInType(tp.resultType)(tparam)
case ExprType(restpe) =>
varianceInType(restpe)(tparam)
case tp @ HKApply(tycon, args) =>
diff --git a/compiler/src/dotty/tools/io/Jar.scala b/compiler/src/dotty/tools/io/Jar.scala
index 42efc7e06..142226ea5 100644
--- a/compiler/src/dotty/tools/io/Jar.scala
+++ b/compiler/src/dotty/tools/io/Jar.scala
@@ -12,6 +12,7 @@ import java.util.jar._
import scala.collection.JavaConverters._
import Attributes.Name
import scala.language.{postfixOps, implicitConversions}
+import scala.annotation.tailrec
// Attributes.Name instances:
//
@@ -109,7 +110,7 @@ class JarWriter(val file: File, val manifest: Manifest) {
private def transfer(in: InputStream, out: OutputStream) = {
val buf = new Array[Byte](10240)
- def loop(): Unit = in.read(buf, 0, buf.length) match {
+ @tailrec def loop(): Unit = in.read(buf, 0, buf.length) match {
case -1 => in.close()
case n => out.write(buf, 0, n) ; loop
}
diff --git a/compiler/src/strawman/collections/CollectionStrawMan6.scala b/compiler/src/strawman/collections/CollectionStrawMan6.scala
index 50de63488..c2b87cb0b 100644
--- a/compiler/src/strawman/collections/CollectionStrawMan6.scala
+++ b/compiler/src/strawman/collections/CollectionStrawMan6.scala
@@ -244,7 +244,7 @@ object CollectionStrawMan6 extends LowPriority {
* collection type.
*/
override def drop(n: Int): C[A @uncheckedVariance] = { // sound bcs of VarianceNote
- def loop(n: Int, s: Iterable[A]): C[A] =
+ @tailrec def loop(n: Int, s: Iterable[A]): C[A] =
if (n <= 0) s.asInstanceOf[C[A]]
// implicit contract to guarantee success of asInstanceOf:
// (1) coll is of type C[A]