summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/Interpreter.scala4
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala6
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreeInfo.scala2
-rw-r--r--src/compiler/scala/tools/nsc/dependencies/Changes.scala2
-rw-r--r--src/compiler/scala/tools/nsc/dependencies/DependencyAnalysis.scala4
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala10
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/Completion.scala6
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/CompletionOutput.scala2
-rw-r--r--src/compiler/scala/tools/nsc/symtab/AnnotationInfos.scala2
-rw-r--r--src/compiler/scala/tools/nsc/symtab/BaseTypeSeqs.scala2
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Definitions.scala14
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Symbols.scala5
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Types.scala181
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala2
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala8
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala2
-rw-r--r--src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala4
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/Reifiers.scala4
-rw-r--r--src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala4
-rw-r--r--src/compiler/scala/tools/nsc/transform/UnCurry.scala33
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/DeVirtualize.scala6
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Implicits.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala43
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala20
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala14
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala4
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala10
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Variances.scala2
-rw-r--r--src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala5
-rw-r--r--src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala4
-rw-r--r--src/library/scala/reflect/Print.scala2
-rw-r--r--src/library/scala/reflect/Type.scala3
-rwxr-xr-xsrc/library/scala/reflect/generic/Types.scala8
-rwxr-xr-xsrc/library/scala/reflect/generic/UnPickler.scala29
-rw-r--r--test/files/lib/scalacheck.jar.desired.sha12
-rw-r--r--test/files/pos/t2741/2741-1.scala13
-rw-r--r--test/files/pos/t2741/2741-2.scala5
39 files changed, 280 insertions, 193 deletions
diff --git a/src/compiler/scala/tools/nsc/Interpreter.scala b/src/compiler/scala/tools/nsc/Interpreter.scala
index e5bc1cf732..e36877837c 100644
--- a/src/compiler/scala/tools/nsc/Interpreter.scala
+++ b/src/compiler/scala/tools/nsc/Interpreter.scala
@@ -156,7 +156,7 @@ class Interpreter(val settings: Settings, out: PrintWriter) {
else null
}
- import compiler.{ Traverser, CompilationUnit, Symbol, Name, TermName, TypeName, Type, TypeRef, PolyType }
+ import compiler.{ Traverser, CompilationUnit, Symbol, Name, TermName, TypeName, Type, TypeRef, NullaryMethodType }
import compiler.{
Tree, TermTree, ValOrDefDef, ValDef, DefDef, Assign, ClassDef,
ModuleDef, Ident, BackQuotedIdent, Select, TypeDef, Import, MemberDef, DocDef,
@@ -1008,7 +1008,7 @@ class Interpreter(val settings: Settings, out: PrintWriter) {
def toType(name: Name): T = {
// the types are all =>T; remove the =>
val tp1 = afterTyper(resObjSym.info.nonPrivateDecl(name).tpe match {
- case PolyType(Nil, tp) => tp
+ case NullaryMethodType(tp) => tp
case tp => tp
})
// normalize non-public types so we don't see protected aliases like Self
diff --git a/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala b/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala
index 8fa27c04f6..969790eabc 100644
--- a/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala
@@ -652,6 +652,12 @@ abstract class TreeBrowsers {
toDocument(result) :: ")")
)
+ case NullaryMethodType(result) =>
+ Document.group(
+ Document.nest(4,"NullaryMethodType(" :/:
+ toDocument(result) :: ")")
+ )
+
case PolyType(tparams, result) =>
Document.group(
Document.nest(4,"PolyType(" :/:
diff --git a/src/compiler/scala/tools/nsc/ast/TreeInfo.scala b/src/compiler/scala/tools/nsc/ast/TreeInfo.scala
index c2623ca5cc..78c7c9e3f0 100644
--- a/src/compiler/scala/tools/nsc/ast/TreeInfo.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreeInfo.scala
@@ -97,7 +97,7 @@ abstract class TreeInfo {
}
def mayBeVarGetter(sym: Symbol) = sym.info match {
- case PolyType(Nil, _) => sym.owner.isClass && !sym.isStable
+ case NullaryMethodType(_) => sym.owner.isClass && !sym.isStable
case mt @ MethodType(_, _) => mt.isImplicit && sym.owner.isClass && !sym.isStable
case _ => false
}
diff --git a/src/compiler/scala/tools/nsc/dependencies/Changes.scala b/src/compiler/scala/tools/nsc/dependencies/Changes.scala
index 9794d71db1..42ccb2de0b 100644
--- a/src/compiler/scala/tools/nsc/dependencies/Changes.scala
+++ b/src/compiler/scala/tools/nsc/dependencies/Changes.scala
@@ -116,6 +116,8 @@ abstract class Changes {
mt1.isImplicit == mt2.isImplicit
case (PolyType(tparams1, res1), PolyType(tparams2, res2)) =>
sameTypeParams(tparams1, tparams2) && sameType(res1, res2)
+ case (NullaryMethodType(res1), NullaryMethodType(res2)) =>
+ sameType(res1, res2)
case (ExistentialType(tparams1, res1), ExistentialType(tparams2, res2)) =>
sameTypeParams(tparams1, tparams2)(false) && sameType(res1, res2)(false)
case (TypeBounds(lo1, hi1), TypeBounds(lo2, hi2)) =>
diff --git a/src/compiler/scala/tools/nsc/dependencies/DependencyAnalysis.scala b/src/compiler/scala/tools/nsc/dependencies/DependencyAnalysis.scala
index e9cc191167..3e8c9cfea7 100644
--- a/src/compiler/scala/tools/nsc/dependencies/DependencyAnalysis.scala
+++ b/src/compiler/scala/tools/nsc/dependencies/DependencyAnalysis.scala
@@ -234,6 +234,10 @@ trait DependencyAnalysis extends SubComponent with Files {
checkType(t.resultType)
updateReferences(t.typeSymbol.fullName)
+ case t: NullaryMethodType =>
+ checkType(t.resultType)
+ updateReferences(t.typeSymbol.fullName)
+
case t =>
updateReferences(t.typeSymbol.fullName)
}
diff --git a/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala b/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala
index 449fdca7b9..fb6d20848f 100644
--- a/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala
@@ -132,6 +132,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { thisFactory
def resultTpe(tpe: Type): Type = tpe match { // similar to finalResultType, except that it leaves singleton types alone
case PolyType(_, res) => resultTpe(res)
case MethodType(_, res) => resultTpe(res)
+ case NullaryMethodType(res) => resultTpe(res)
case _ => tpe
}
makeType(resultTpe(sym.tpe), inTemplate, sym)
@@ -577,8 +578,12 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { thisFactory
if (!defs.isEmpty) {
nameBuffer append " {...}" // TODO: actually print the refinement
}
+ /* Eval-by-name types */
+ case NullaryMethodType(result) =>
+ nameBuffer append '⇒'
+ appendType0(result)
/* Polymorphic types */
- case PolyType(tparams, result) if tparams nonEmpty =>
+ case PolyType(tparams, result) => assert(tparams nonEmpty)
// throw new Error("Polymorphic type '" + tpe + "' cannot be printed as a type")
def typeParamsToString(tps: List[Symbol]): String = if(tps isEmpty) "" else
tps.map{tparam =>
@@ -586,9 +591,6 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { thisFactory
}.mkString("[", ", ", "]")
nameBuffer append typeParamsToString(tparams)
appendType0(result)
- case PolyType(tparams, result) if (tparams.isEmpty) =>
- nameBuffer append '⇒'
- appendType0(result)
case tpen =>
nameBuffer append tpen.toString
}
diff --git a/src/compiler/scala/tools/nsc/interpreter/Completion.scala b/src/compiler/scala/tools/nsc/interpreter/Completion.scala
index 971146ea14..bb177a9946 100644
--- a/src/compiler/scala/tools/nsc/interpreter/Completion.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/Completion.scala
@@ -66,9 +66,9 @@ class Completion(val repl: Interpreter) extends CompletionOutput {
trait CompilerCompletion {
def tp: Type
def effectiveTp = tp match {
- case MethodType(Nil, resType) => resType
- case PolyType(Nil, resType) => resType
- case _ => tp
+ case MethodType(Nil, resType) => resType
+ case NullaryMethodType(resType) => resType
+ case _ => tp
}
// for some reason any's members don't show up in subclasses, which
diff --git a/src/compiler/scala/tools/nsc/interpreter/CompletionOutput.scala b/src/compiler/scala/tools/nsc/interpreter/CompletionOutput.scala
index e0d678b961..e977e28922 100644
--- a/src/compiler/scala/tools/nsc/interpreter/CompletionOutput.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/CompletionOutput.scala
@@ -77,7 +77,7 @@ trait CompletionOutput {
def methodString() =
method.keyString + " " + method.nameString + (method.info.normalize match {
- case PolyType(Nil, resType) => ": " + typeToString(resType) // nullary method
+ case NullaryMethodType(resType) => ": " + typeToString(resType)
case PolyType(tparams, resType) => tparamsString(tparams) + typeToString(resType)
case mt @ MethodType(_, _) => methodTypeToString(mt)
case x =>
diff --git a/src/compiler/scala/tools/nsc/symtab/AnnotationInfos.scala b/src/compiler/scala/tools/nsc/symtab/AnnotationInfos.scala
index 2429f53aa1..24672cc411 100644
--- a/src/compiler/scala/tools/nsc/symtab/AnnotationInfos.scala
+++ b/src/compiler/scala/tools/nsc/symtab/AnnotationInfos.scala
@@ -107,6 +107,8 @@ trait AnnotationInfos extends reflect.generic.AnnotationInfos { self: SymbolTabl
this
}
+ lazy val isTrivial: Boolean = atp.isTrivial && !(args exists (_.exists(_.isInstanceOf[This]))) // see annotationArgRewriter
+
override def toString: String = atp +
(if (!args.isEmpty) args.mkString("(", ", ", ")") else "") +
(if (!assocs.isEmpty) (assocs map { case (x, y) => x+" = "+y } mkString ("(", ", ", ")")) else "")
diff --git a/src/compiler/scala/tools/nsc/symtab/BaseTypeSeqs.scala b/src/compiler/scala/tools/nsc/symtab/BaseTypeSeqs.scala
index 72dc5b9e91..5c0fe74967 100644
--- a/src/compiler/scala/tools/nsc/symtab/BaseTypeSeqs.scala
+++ b/src/compiler/scala/tools/nsc/symtab/BaseTypeSeqs.scala
@@ -149,6 +149,8 @@ trait BaseTypeSeqs {
max(maxDpth(lo), maxDpth(hi))
case MethodType(paramtypes, result) =>
maxDpth(result)
+ case NullaryMethodType(result) =>
+ maxDpth(result)
case PolyType(tparams, result) =>
max(maxDpth(result), maxDpth(tparams map (_.info)) + 1)
case ExistentialType(tparams, result) =>
diff --git a/src/compiler/scala/tools/nsc/symtab/Definitions.scala b/src/compiler/scala/tools/nsc/symtab/Definitions.scala
index 340ab09c81..ecda252ec6 100644
--- a/src/compiler/scala/tools/nsc/symtab/Definitions.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Definitions.scala
@@ -28,7 +28,7 @@ trait Definitions extends reflect.generic.StandardDefinitions {
lazy val RootPackage: Symbol = {
val rp = NoSymbol.newValue(NoPosition, nme.ROOTPKG)
.setFlag(FINAL | MODULE | PACKAGE | JAVA)
- .setInfo(PolyType(List(), RootClass.tpe))
+ .setInfo(NullaryMethodType(RootClass.tpe))
RootClass.sourceModule = rp
rp
}
@@ -227,7 +227,7 @@ trait Definitions extends reflect.generic.StandardDefinitions {
)
lazy val EqualsPatternClass = {
val clazz = newClass(ScalaPackageClass, tpnme.EQUALS_PATTERN_NAME, Nil)
- clazz setInfo PolyType(List(newTypeParam(clazz, 0)), ClassInfoType(anyparam, new Scope, clazz))
+ clazz setInfo polyType(List(newTypeParam(clazz, 0)), ClassInfoType(anyparam, new Scope, clazz))
}
// collections classes
@@ -587,7 +587,7 @@ trait Definitions extends reflect.generic.StandardDefinitions {
else*/ List(p)
println("creating " + name + " with parents " + parents) */
clazz.setInfo(
- PolyType(
+ polyType(
List(tparam),
ClassInfoType(List(AnyRefClass.tpe, p), new Scope, clazz)))
}
@@ -619,11 +619,11 @@ trait Definitions extends reflect.generic.StandardDefinitions {
private def newPolyMethodCon(owner: Symbol, name: TermName, tcon: Symbol => Symbol => Type): Symbol = {
val msym = newMethod(owner, name)
val tparam = newTypeParam(msym, 0)
- msym.setInfo(PolyType(List(tparam), tcon(tparam)(msym)))
+ msym.setInfo(polyType(List(tparam), tcon(tparam)(msym)))
}
private def newParameterlessMethod(owner: Symbol, name: TermName, restpe: Type) =
- newMethod(owner, name).setInfo(PolyType(List(),restpe))
+ newMethod(owner, name).setInfo(NullaryMethodType(restpe))
private def newTypeParam(owner: Symbol, index: Int): Symbol =
owner.newTypeParameter(NoPosition, newTypeName("T" + index)) setInfo TypeBounds.empty
@@ -889,9 +889,9 @@ trait Definitions extends reflect.generic.StandardDefinitions {
Any_## = newMethod(AnyClass, nme.HASHHASH, Nil, inttype) setFlag FINAL
Any_isInstanceOf = newPolyMethod(
- AnyClass, nme.isInstanceOf_, tparam => booltype) setFlag FINAL
+ AnyClass, nme.isInstanceOf_, tparam => NullaryMethodType(booltype)) setFlag FINAL
Any_asInstanceOf = newPolyMethod(
- AnyClass, nme.asInstanceOf_, tparam => tparam.typeConstructor) setFlag FINAL
+ AnyClass, nme.asInstanceOf_, tparam => NullaryMethodType(tparam.typeConstructor)) setFlag FINAL
// members of class java.lang.{ Object, String }
Object_## = newMethod(ObjectClass, nme.HASHHASH, Nil, inttype) setFlag FINAL
diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
index c269472aa3..12f044aafe 100644
--- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
@@ -510,6 +510,7 @@ trait Symbols extends reflect.generic.Symbols { self: SymbolTable =>
case ConstantType(_) => true
case PolyType(_, ConstantType(_)) => true
case MethodType(_, ConstantType(_)) => true
+ case NullaryMethodType(ConstantType(_)) => true
case _ => false
})
@@ -1604,8 +1605,10 @@ trait Symbols extends reflect.generic.Symbols { self: SymbolTable =>
tp match {
case PolyType(tparams, res) =>
typeParamsString + infoString(res)
+ case NullaryMethodType(res) =>
+ infoString(res)
case MethodType(params, res) =>
- params.map(_.defString).mkString("(", ",", ")") + infoString(res)
+ params.map(_.defString).mkString("(", ",", ")") + infoString(res)
case _ =>
": " + tp
}
diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala
index f302f5c6ea..cbecd073f6 100644
--- a/src/compiler/scala/tools/nsc/symtab/Types.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Types.scala
@@ -50,14 +50,13 @@ import scala.annotation.tailrec
case MethodType(paramtypes, result) =>
// (paramtypes)result
// For instance def m(): T is represented as MethodType(List(), T)
+ case NullaryMethodType(result) => // eliminated by uncurry
+ // an eval-by-name type
+ // For instance def m: T is represented as NullaryMethodType(T)
case PolyType(tparams, result) =>
- // [tparams]result where result is a MethodType or ClassInfoType
- // or
- // []T for a eval-by-name type
- // For instance def m: T is represented as PolyType(List(), T)
+ // [tparams]result where result is a (Nullary)MethodType or ClassInfoType
// The remaining types are not used after phase `typer'.
-
case OverloadedType(pre, tparams, alts) =>
// all alternatives of an overloaded ident
case AntiPolyType(pre, targs) =>
@@ -365,7 +364,7 @@ trait Types extends reflect.generic.Types { self: SymbolTable =>
/** For a typeref, its arguments. The empty list for all other types */
def typeArgs: List[Type] = List()
- /** For a method or poly type, its direct result type,
+ /** For a (nullary) method or poly type, its direct result type,
* the type itself for all other types. */
def resultType: Type = this
@@ -379,11 +378,11 @@ trait Types extends reflect.generic.Types { self: SymbolTable =>
*/
def remove(clazz: Symbol): Type = this
- /** For a curried method or poly type its non-method result type,
+ /** For a curried/nullary method or poly type its non-method result type,
* the type itself for all other types */
def finalResultType: Type = this
- /** For a method or poly type, the number of its value parameter sections,
+ /** For a method type, the number of its value parameter sections,
* 0 for all other types */
def paramSectionCount: Int = 0
@@ -708,7 +707,7 @@ trait Types extends reflect.generic.Types { self: SymbolTable =>
* - Either both types are polytypes with the same number of
* type parameters and their result types match after renaming
* corresponding type parameters
- * - Or both types are method types with equivalent type parameter types
+ * - Or both types are (nullary) method types with equivalent type parameter types
* and matching result types
* - Or both types are equivalent
* - Or phase.erasedTypes is false and both types are neither method nor
@@ -1137,14 +1136,6 @@ trait Types extends reflect.generic.Types { self: SymbolTable =>
else sym.tpe
}
- // case class DeBruijnIndex(level: Int, paramId: Int) extends Type {
- // override def isTrivial = true
- // override def isStable = true
- // override def safeToString = "<param "+level+"."+paramId+">"
- // override def kind = "DeBruijnIndex"
- // // todo: this should be a subtype, which forwards to underlying
- // }
-
/** A class for singleton types of the form <prefix>.<sym.name>.type.
* Cannot be created directly; one should always use
* `singleType' for creation.
@@ -1416,7 +1407,7 @@ trait Types extends reflect.generic.Types { self: SymbolTable =>
*/
override def normalize = {
if (isHigherKinded) {
- PolyType(
+ typeFun(
typeParams,
RefinedType(
parents map {
@@ -1807,11 +1798,10 @@ A type's typeSymbol should never be inspected directly.
transform(sym.info.resultType)
}
- // @M TODO: should not use PolyType, as that's the type of a polymorphic value -- we really want a type *function*
// @M: initialize (by sym.info call) needed (see test/files/pos/ticket0137.scala)
@inline private def etaExpand: Type = {
val tpars = sym.info.typeParams // must go through sym.info for typeParams to initialise symbol
- PolyType(tpars, typeRef(pre, sym, tpars map (_.tpeHK))) // todo: also beta-reduce?
+ typeFunAnon(tpars, typeRef(pre, sym, tpars map (_.tpeHK))) // todo: also beta-reduce?
}
override def dealias: Type =
@@ -1963,11 +1953,10 @@ A type's typeSymbol should never be inspected directly.
}
/** A class representing a method type with parameters.
- * Note that a parameterless method is instead encoded
- * as a PolyType, as shown here:
+ * Note that a parameterless method is represented by a NullaryMethodType:
*
* def m(): Int MethodType(Nil, Int)
- * def m: Int PolyType(Nil, Int)
+ * def m: Int NullaryMethodType(Int)
*/
case class MethodType(override val params: List[Symbol],
override val resultType: Type) extends Type {
@@ -1989,6 +1978,7 @@ A type's typeSymbol should never be inspected directly.
override def boundSyms = immutable.Set[Symbol](params ++ resultType.boundSyms: _*)
+ // AM to TR: #dropNonContraintAnnotations
// this is needed for plugins to work correctly, only TypeConstraint annotations are supposed to be carried over
// TODO: this should probably be handled in a more structured way in adapt -- remove this map in resultType and watch the continuations tests fail
object dropNonContraintAnnotations extends TypeMap {
@@ -2040,18 +2030,47 @@ A type's typeSymbol should never be inspected directly.
override def isJava = true
}
- /** A class representing a polymorphic type or, if typeParams.isEmpty, a parameterless method type.
+ case class NullaryMethodType(override val resultType: Type) extends Type {
+ // AM to TR: #dropNonContraintAnnotations
+ // change isTrivial to the commented version and watch continuations-run/t3225.scala fail
+ // isTrivial implies asSeenFrom is bypassed, since it's supposed to be the identity map
+ // it's not really the identity due to dropNonContraintAnnotations
+ override def isTrivial: Boolean = false //resultType.isTrivial -- `false` to make continuations plugin work (so that asSeenFromMap drops non-constrain annotations even when type doesn't change otherwise)
+ override def prefix: Type = resultType.prefix
+ override def narrow: Type = resultType.narrow
+ override def finalResultType: Type = resultType.finalResultType
+ override def termSymbol: Symbol = resultType.termSymbol
+ override def typeSymbol: Symbol = resultType.typeSymbol
+ override def parents: List[Type] = resultType.parents
+ override def decls: Scope = resultType.decls
+ override def baseTypeSeq: BaseTypeSeq = resultType.baseTypeSeq
+ override def baseTypeSeqDepth: Int = resultType.baseTypeSeqDepth
+ override def baseClasses: List[Symbol] = resultType.baseClasses
+ override def baseType(clazz: Symbol): Type = resultType.baseType(clazz)
+ override def boundSyms = resultType.boundSyms
+ override def isVolatile = resultType.isVolatile
+ override def safeToString: String = "=> "+ resultType
+ override def kind = "NullaryMethodType"
+ }
+
+ object NullaryMethodType extends NullaryMethodTypeExtractor
+
+ /** A type function or the type of a polymorphic value (and thus of kind *).
+ *
+ * Before the introduction of NullaryMethodType, a polymorphic nullary method (e.g, def isInstanceOf[T]: Boolean)
+ * used to be typed as PolyType(tps, restpe), and a monomorphic one as PolyType(Nil, restpe)
+ * This is now: PolyType(tps, NullaryMethodType(restpe)) and NullaryMethodType(restpe)
+ * by symmetry to MethodTypes: PolyType(tps, MethodType(params, restpe)) and MethodType(params, restpe)
+ *
+ * Thus, a PolyType(tps, TypeRef(...)) unambiguously indicates a type function (which results from eta-expanding a type constructor alias).
+ * Similarly, PolyType(tps, ClassInfoType(...)) is a type constructor.
*
- * (@M: note that polymorphic nullary methods have non-empty tparams,
- * e.g., isInstanceOf or def makeList[T] = new List[T].
- * Ideally, there would be a NullaryMethodType, but since the only polymorphic values are methods, it's not that problematic.
- * More pressingly, we should add a TypeFunction type for anonymous type constructors -- for now, PolyType is used in:
- * - normalize: for eta-expansion of type aliases
- * - typeDefSig )
+ * A polytype is of kind * iff its resultType is a (nullary) method type.
*/
case class PolyType(override val typeParams: List[Symbol], override val resultType: Type)
extends Type {
- // assert(!(typeParams contains NoSymbol), this)
+ //assert(!(typeParams contains NoSymbol), this)
+ assert(typeParams nonEmpty, this) // used to be a marker for nullary method type, illegal now (see @NullaryMethodType)
override def paramSectionCount: Int = resultType.paramSectionCount
override def paramss: List[List[Symbol]] = resultType.paramss
@@ -2071,19 +2090,18 @@ A type's typeSymbol should never be inspected directly.
override def isVolatile = resultType.isVolatile
override def finalResultType: Type = resultType.finalResultType
- /** @M: typeDefSig now wraps a TypeBounds in a PolyType
+ /** @M: typeDefSig wraps a TypeBounds in a PolyType
* to represent a higher-kinded type parameter
* wrap lo&hi in polytypes to bind variables
*/
override def bounds: TypeBounds =
- TypeBounds(PolyType(typeParams, resultType.bounds.lo),
- PolyType(typeParams, resultType.bounds.hi))
+ TypeBounds(typeFun(typeParams, resultType.bounds.lo),
+ typeFun(typeParams, resultType.bounds.hi))
override def isHigherKinded = !typeParams.isEmpty
override def safeToString: String =
- (if (typeParams.isEmpty) "=> "
- else (typeParams map (_.defString) mkString ("[", ",", "]")))+resultType
+ (typeParams map (_.defString) mkString ("[", ",", "]"))+ resultType
override def cloneInfo(owner: Symbol) = {
val tparams = cloneSymbols(typeParams, owner)
@@ -2167,7 +2185,7 @@ A type's typeSymbol should never be inspected directly.
}
var ustr = underlying.toString
underlying match {
- case MethodType(_, _) | PolyType(_, _) => ustr = "("+ustr+")"
+ case MethodType(_, _) | NullaryMethodType(_) | PolyType(_, _) => ustr = "("+ustr+")"
case _ =>
}
val str =
@@ -2439,8 +2457,7 @@ A type's typeSymbol should never be inspected directly.
override def normalize: Type =
if (constr.instValid) constr.inst
else if (isHigherKinded) { // get here when checking higher-order subtyping of the typevar by itself (TODO: check whether this ever happens?)
- // @M TODO: should not use PolyType, as that's the type of a polymorphic value -- we really want a type *function*
- PolyType(params, applyArgs(params map (_.typeConstructor)))
+ typeFun(params, applyArgs(params map (_.typeConstructor)))
} else {
super.normalize
}
@@ -2483,6 +2500,9 @@ A type's typeSymbol should never be inspected directly.
override protected def rewrap(tp: Type) = AnnotatedType(annotations, tp, selfsym)
+ override def isTrivial: Boolean = isTrivial0
+ private lazy val isTrivial0 = underlying.isTrivial && (annotations forall (_.isTrivial))
+
override def safeToString: String = {
val attString =
if (annotations.isEmpty)
@@ -2725,16 +2745,24 @@ A type's typeSymbol should never be inspected directly.
case _ => abort(debugString(tycon))
}
- /** A creator for type parameterizations
- * If tparams is empty, simply returns result type
+ /** A creator for type parameterizations that strips empty type parameter lists.
+ * Use this factory method to indicate the type has kind * (it's a polymorphic value)
+ * until we start tracking explicit kinds equivalent to typeFun (except that the latter requires tparams nonEmpty)
*/
def polyType(tparams: List[Symbol], tpe: Type): Type =
- if (tparams.isEmpty) tpe
- else
- PolyType(tparams, tpe match {
- case PolyType(List(), tpe1) => tpe1
- case _ => tpe
- })
+ if (tparams nonEmpty) typeFun(tparams, tpe)
+ else tpe // it's okay to be forgiving here
+
+ /** A creator for anonymous type functions, where the symbol for the type function still needs to be created
+ * TODO_NMT:
+ * - can we avoid this whole synthetic owner business? harden ASF instead to deal with orphan type params
+ * - orthogonally: try to recycle the class symbol in the common case type C[X] = Class[X] (where appliedType(this, dummyArgs) =:= appliedType(sym.info, dummyArgs))
+ */
+ def typeFunAnon(tps: List[Symbol], body: Type): Type = typeFun(tps, body)
+
+ /** A creator for a type functions, assuming the type parameters tps already have the right owner
+ */
+ def typeFun(tps: List[Symbol], body: Type): Type = PolyType(tps, body)
/** A creator for existential types. This generates:
*
@@ -3011,8 +3039,11 @@ A type's typeSymbol should never be inspected directly.
var result1 = this(result)
if ((tparams1 eq tparams) && (result1 eq result)) tp
else PolyType(tparams1, result1.substSym(tparams, tparams1))
+ case NullaryMethodType(result) =>
+ val result1 = this(result)
+ if (result1 eq result) tp
+ else NullaryMethodType(result1)
case ConstantType(_) => tp
- // case DeBruijnIndex(_, _) => tp
case SuperType(thistp, supertp) =>
val thistp1 = this(thistp)
val supertp1 = this(supertp)
@@ -3251,13 +3282,13 @@ A type's typeSymbol should never be inspected directly.
override def mapOver(tree: Tree, giveup: ()=>Nothing): Tree = {
object annotationArgRewriter extends TypeMapTransformer {
- /** Rewrite "this" trees as needed for asSeenFrom */
+ /** Rewrite `This` trees in annotation argument trees */
def rewriteThis(tree: Tree): Tree =
tree match {
case This(_)
if (tree.symbol isNonBottomSubClass clazz) &&
(pre.widen.typeSymbol isNonBottomSubClass tree.symbol) =>
- if (pre.isStable) {
+ if (pre.isStable) { // XXX why is this in this method? pull it out and guard the call `annotationArgRewriter.transform(tree)`?
val termSym =
pre.typeSymbol.owner.newValue(
pre.typeSymbol.pos,
@@ -3846,6 +3877,10 @@ A type's typeSymbol should never be inspected directly.
val restp1 = this(restp)
if (restp1 eq restp) tp
else copyMethodType(tp, params, restp1)
+ case NullaryMethodType(restp) =>
+ val restp1 = this(restp)
+ if (restp1 eq restp) tp
+ else NullaryMethodType(restp1)
case PolyType(tparams, restp) =>
val restp1 = this(restp)
if (restp1 eq restp) tp
@@ -4235,6 +4270,14 @@ A type's typeSymbol should never be inspected directly.
return isSameTypes(mt1.paramTypes, mt2.paramTypes) &&
mt1.resultType =:= mt2.resultType &&
mt1.isImplicit == mt2.isImplicit
+ // note: no case NullaryMethodType(restpe) => return mt1.params.isEmpty && mt1.resultType =:= restpe
+ case _ =>
+ }
+ case NullaryMethodType(restpe1) =>
+ tp2 match {
+ // note: no case mt2: MethodType => return mt2.params.isEmpty && restpe =:= mt2.resultType
+ case NullaryMethodType(restpe2) =>
+ return restpe1 =:= restpe2
case _ =>
}
case PolyType(tparams1, res1) =>
@@ -4584,13 +4627,14 @@ A type's typeSymbol should never be inspected directly.
matchingParams(params1, params2, mt1.isJava, mt2.isJava) &&
(res1 <:< res2) &&
mt1.isImplicit == mt2.isImplicit)
+ // TODO: if mt1.params.isEmpty, consider NullaryMethodType?
case _ =>
false
}
- case pt2 @ PolyType(List(), _) =>
+ case pt2 @ NullaryMethodType(_) =>
tp1 match {
- case pt1 @ PolyType(List(), _) =>
- // other polytypes were already checked in isHKSubType
+ // TODO: consider MethodType mt for which mt.params.isEmpty??
+ case pt1 @ NullaryMethodType(_) =>
pt1.resultType <:< pt2.resultType
case _ =>
false
@@ -4706,7 +4750,7 @@ A type's typeSymbol should never be inspected directly.
matchingParams(params1, params2, mt1.isJava, mt2.isJava) &&
matchesType(res1, res2, alwaysMatchSimple) &&
mt1.isImplicit == mt2.isImplicit
- case PolyType(List(), res2) =>
+ case NullaryMethodType(res2) =>
if (params1.isEmpty) matchesType(res1, res2, alwaysMatchSimple)
else matchesType(tp1, res2, alwaysMatchSimple)
case ExistentialType(_, res2) =>
@@ -4714,16 +4758,25 @@ A type's typeSymbol should never be inspected directly.
case _ =>
false
}
+ case mt1 @ NullaryMethodType(res1) =>
+ tp2 match {
+ case mt2 @ MethodType(Nil, res2) => // could never match if params nonEmpty, and !mt2.isImplicit is implied by empty param list
+ matchesType(res1, res2, alwaysMatchSimple)
+ case NullaryMethodType(res2) =>
+ matchesType(res1, res2, alwaysMatchSimple)
+ case ExistentialType(_, res2) =>
+ alwaysMatchSimple && matchesType(tp1, res2, true)
+ case _ =>
+ matchesType(res1, tp2, alwaysMatchSimple)
+ }
case PolyType(tparams1, res1) =>
tp2 match {
case PolyType(tparams2, res2) =>
matchesQuantified(tparams1, tparams2, res1, res2)
- case MethodType(List(), res2) if (tparams1.isEmpty) =>
- matchesType(res1, res2, alwaysMatchSimple)
case ExistentialType(_, res2) =>
alwaysMatchSimple && matchesType(tp1, res2, true)
case _ =>
- tparams1.isEmpty && matchesType(res1, tp2, alwaysMatchSimple)
+ false // remember that tparams1.nonEmpty is now an invariant of PolyType
}
case ExistentialType(tparams1, res1) =>
tp2 match {
@@ -4752,9 +4805,9 @@ A type's typeSymbol should never be inspected directly.
tp1.isImplicit == tp2.isImplicit
case (PolyType(tparams1, res1), PolyType(tparams2, res2)) =>
matchesQuantified(tparams1, tparams2, res1, res2)
- case (PolyType(List(), rtp1), MethodType(List(), rtp2)) =>
+ case (NullaryMethodType(rtp1), MethodType(List(), rtp2)) =>
matchesType(rtp1, rtp2, alwaysMatchSimple)
- case (MethodType(List(), rtp1), PolyType(List(), rtp2)) =>
+ case (MethodType(List(), rtp1), NullaryMethodType(rtp2)) =>
matchesType(rtp1, rtp2, alwaysMatchSimple)
case (ExistentialType(tparams1, res1), ExistentialType(tparams2, res2)) =>
matchesQuantified(tparams1, tparams2, res1, res2)
@@ -4762,9 +4815,9 @@ A type's typeSymbol should never be inspected directly.
matchesType(res1, tp2, alwaysMatchSimple)
case (_, ExistentialType(_, res2)) if alwaysMatchSimple =>
matchesType(tp1, res2, alwaysMatchSimple)
- case (PolyType(List(), rtp1), _) =>
+ case (NullaryMethodType(rtp1), _) =>
matchesType(rtp1, tp2, alwaysMatchSimple)
- case (_, PolyType(List(), rtp2)) =>
+ case (_, NullaryMethodType(rtp2)) =>
matchesType(tp1, rtp2, alwaysMatchSimple)
case (MethodType(_, _), _) => false
case (PolyType(_, _), _) => false
@@ -5077,6 +5130,8 @@ A type's typeSymbol should never be inspected directly.
PolyType(tparams1, lub0(matchingInstTypes(ts, tparams1)))
case ts @ MethodType(params, _) :: rest =>
MethodType(params, lub0(matchingRestypes(ts, params map (_.tpe))))
+ case ts @ NullaryMethodType(_) :: rest =>
+ NullaryMethodType(lub0(matchingRestypes(ts, Nil)))
case ts @ TypeBounds(_, _) :: rest =>
TypeBounds(glb(ts map (_.bounds.lo), depth), lub(ts map (_.bounds.hi), depth))
case ts =>
@@ -5192,6 +5247,8 @@ A type's typeSymbol should never be inspected directly.
PolyType(tparams1, glb0(matchingInstTypes(ts, tparams1)))
case ts @ MethodType(params, _) :: rest =>
MethodType(params, glb0(matchingRestypes(ts, params map (_.tpe))))
+ case ts @ NullaryMethodType(_) :: rest =>
+ NullaryMethodType(glb0(matchingRestypes(ts, Nil)))
case ts @ TypeBounds(_, _) :: rest =>
TypeBounds(lub(ts map (_.bounds.lo), depth), glb(ts map (_.bounds.hi), depth))
case ts =>
@@ -5433,6 +5490,8 @@ A type's typeSymbol should never be inspected directly.
tps map {
case MethodType(params1, res) if (isSameTypes(params1 map (_.tpe), pts)) =>
res
+ case NullaryMethodType(res) if pts isEmpty =>
+ res
case _ =>
throw new NoCommonType(tps)
}
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
index 253ebb708d..20f990d057 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
@@ -1261,7 +1261,7 @@ abstract class ClassfileParser {
override def complete(sym: Symbol) {
alias.initialize
val tparams1 = cloneSymbols(alias.typeParams)
- sym.setInfo(polyType(tparams1, alias.tpe.substSym(alias.typeParams, tparams1)))
+ sym.setInfo(typeFun(tparams1, alias.tpe.substSym(alias.typeParams, tparams1)))
}
}
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala
index 246bb6a88d..050b59118d 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala
@@ -182,6 +182,8 @@ abstract class Pickler extends SubComponent {
putSymbol(clazz); putTypes(parents); putSymbols(decls.toList)
case MethodType(params, restpe) =>
putType(restpe); putSymbols(params)
+ case NullaryMethodType(restpe) =>
+ putType(restpe)
case PolyType(tparams, restpe) =>
/** no longer needed since all params are now local
tparams foreach { tparam =>
@@ -575,7 +577,11 @@ abstract class Pickler extends SubComponent {
writeRef(restpe); writeRefs(formals)
if (mt.isImplicit) IMPLICITMETHODtpe
else METHODtpe
- case PolyType(tparams, restpe) =>
+ case mt @ NullaryMethodType(restpe) => // reuse POLYtpe since those can never have an empty list of tparams -- TODO: is there any way this can come back and bite us in the bottom?
+ // ugliness and thrift aside, this should make this somewhat more backward compatible
+ // (I'm not sure how old scalac's would deal with nested PolyTypes, as these used to be folded into one)
+ writeRef(restpe); writeRefs(Nil); POLYtpe
+ case PolyType(tparams, restpe) => // invar: tparams nonEmpty
writeRef(restpe); writeRefs(tparams); POLYtpe
case ExistentialType(tparams, restpe) =>
writeRef(restpe); writeRefs(tparams); EXISTENTIALtpe
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala b/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala
index afafce5abe..3427701899 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala
@@ -50,7 +50,7 @@ abstract class UnPickler extends reflect.generic.UnPickler {
private val definedAtRunId = currentRunId
private val p = phase
override def complete(sym: Symbol) : Unit = {
- val tp = at(i, readType)
+ val tp = at(i, () => readType(sym.isTerm)) // after NMT_TRANSITION, revert `() => readType(sym.isTerm)` to `readType`
if (p != phase) atPhase(p) (sym setInfo tp)
else sym setInfo tp
if (currentRunId != definedAtRunId) sym.setInfo(adaptToNewRunMap(tp))
diff --git a/src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala b/src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala
index 3f5fc6fdcb..80092af22e 100644
--- a/src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala
+++ b/src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala
@@ -309,8 +309,8 @@ abstract class TypeParser {
val flags = translateAttributes(getter);
val owner: Symbol = if (getter.IsStatic) statics else clazz;
val methodSym = owner.newMethod(NoPosition, name).setFlag(flags)
- val mtype: Type = if (gparamsLength == 0) PolyType(List(), propType) // .NET properties can't be polymorphic
- else methodType(getter, getter.ReturnType)(methodSym)
+ val mtype: Type = if (gparamsLength == 0) NullaryMethodType(propType) // .NET properties can't be polymorphic
+ else methodType(getter, getter.ReturnType)(methodSym)
methodSym.setInfo(mtype);
methodSym.setFlag(Flags.ACCESSOR);
(if (getter.IsStatic) staticDefs else instanceDefs).enter(methodSym)
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala
index 998cf69f5e..46707fe445 100644
--- a/src/compiler/scala/tools/nsc/transform/Erasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala
@@ -402,7 +402,7 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer with ast.
val deconstMap = new TypeMap {
def apply(tp: Type): Type = tp match {
case PolyType(_, _) => mapOver(tp)
- case MethodType(_, _) => mapOver(tp)
+ case MethodType(_, _) => mapOver(tp) // nullarymethod was eliminated during uncurry
case _ => tp.deconst
}
}
diff --git a/src/compiler/scala/tools/nsc/transform/Reifiers.scala b/src/compiler/scala/tools/nsc/transform/Reifiers.scala
index 49ae43e1fe..e0ee4d3af8 100644
--- a/src/compiler/scala/tools/nsc/transform/Reifiers.scala
+++ b/src/compiler/scala/tools/nsc/transform/Reifiers.scala
@@ -79,6 +79,8 @@ trait Reifiers {
if (_log_reify_type_) println("cannot handle ClassInfoType "+tp); reflect.NoType
case MethodType(params, result) =>
reflect.MethodType(params.map(reify), reify(result))
+ case NullaryMethodType(result) =>
+ reflect.NullaryMethodType(reify(result))
case PolyType(tparams, result) =>
val boundss =
for {
@@ -146,6 +148,8 @@ trait Reifiers {
TypeBounds(unreify(lo), unreify(hi))
case reflect.MethodType(params, restpe) =>
MethodType(params.map(unreify), unreify(restpe))
+ case reflect.NullaryMethodType(restpe) =>
+ NullaryMethodType(unreify(restpe))
case reflect.PolyType(typeParams, typeBounds, resultType) =>
PolyType(typeParams.map(unreify), unreify(resultType))
//todo: treat ExistentialType
diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
index 387f069875..d8c5370df6 100644
--- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
+++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
@@ -327,6 +327,8 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
case PolyType(tparams, resTpe) =>
specializedTypeVars(tparams map (_.info)) ++ specializedTypeVars(resTpe)
+ case NullaryMethodType(resTpe) => // since this method may be run at phase typer (before uncurry, where NMTs are eliminated)
+ specializedTypeVars(resTpe)
case MethodType(argSyms, resTpe) =>
specializedTypeVars(argSyms map (_.tpe)) ++ specializedTypeVars(resTpe)
@@ -889,7 +891,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
if (settings.debug.value) log("transformInfo (poly) " + clazz + " with parents1: " + parents + " ph: " + phase)
// if (clazz.name.toString == "$colon$colon")
// (new Throwable).printStackTrace
- PolyType(targs, ClassInfoType(parents,
+ polyType(targs, ClassInfoType(parents,
new Scope(specializeClass(clazz, typeEnv(clazz)) ::: specialOverrides(clazz)),
clazz))
diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
index 1a6a36691d..3c8997657c 100644
--- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala
+++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
@@ -66,10 +66,8 @@ abstract class UnCurry extends InfoTransform with TypingTransformers with ast.Tr
tp0
case MethodType(h :: t, restpe) if h.isImplicit =>
apply(MethodType(h.cloneSymbol.resetFlag(IMPLICIT) :: t, restpe))
- case PolyType(List(), restpe) => // nullary method type
+ case NullaryMethodType(restpe) =>
apply(MethodType(List(), restpe))
- case PolyType(tparams, restpe) => // polymorphic nullary method type, since it didn't occur in a higher-kinded position
- PolyType(tparams, apply(MethodType(List(), restpe)))
case TypeRef(pre, ByNameParamClass, List(arg)) =>
apply(functionType(List(), arg))
case TypeRef(pre, RepeatedParamClass, args) =>
@@ -81,29 +79,6 @@ abstract class UnCurry extends InfoTransform with TypingTransformers with ast.Tr
expandAlias(mapOver(tp))
}
}
-
-//@M TODO: better fix for the gross hack that conflates polymorphic nullary method types with type functions
-// `[tpars] tref` (PolyType(tpars, tref)) could uncurry to either:
-// - `[tpars]() tref` (PolyType(tpars, MethodType(List(), tref))
-// a nullary method types uncurry to a method with an empty argument list
-// - `[tpars] tref` (PolyType(tpars, tref))
-// a proper type function -- see mapOverArgs: can only occur in args of TypeRef (right?))
-// the issue comes up when a partial type application gets normalised to a polytype, like `[A] Function1[X, A]`
-// should not apply the uncurry transform to such a type
-// see #2594 for an example
-
- // decide whether PolyType represents a nullary method type (only if type has kind *)
- // for higher-kinded types, leave PolyType intact
- override def mapOverArgs(args: List[Type], tparams: List[Symbol]): List[Type] =
- map2Conserve(args, tparams) { (arg, tparam) =>
- arg match {
- // is this a higher-kinded position? (TODO: confirm this is the only case)
- case PolyType(tparams, restpe) if tparam.typeParams.nonEmpty => // higher-kinded type param
- PolyType(tparams, apply(restpe)) // could not be a nullary method type
- case _ =>
- this(arg)
- }
- }
}
private val uncurryType = new TypeMap {
@@ -640,10 +615,10 @@ abstract class UnCurry extends InfoTransform with TypingTransformers with ast.Tr
def postTransform(tree: Tree): Tree = atPhase(phase.next) {
def applyUnary(): Tree = {
- def needsParens = tree.symbol.isMethod && (!tree.tpe.isInstanceOf[PolyType] || tree.tpe.typeParams.isEmpty)
+ def needsParens = tree.symbol.isMethod && !tree.tpe.isInstanceOf[PolyType] // TODO_NMT: verify that the inner tree of a type-apply also gets parens if the whole tree is a polymorphic nullary method application
def repair = {
- if (!tree.tpe.isInstanceOf[MethodType])
- tree.tpe = MethodType(Nil, tree.tpe)
+ if (!tree.tpe.isInstanceOf[MethodType]) // i.e., it's a NullaryMethodType
+ tree.tpe = MethodType(Nil, tree.tpe.resultType) // TODO_NMT: I think the original `tree.tpe` was wrong, since that would set the method's resulttype to PolyType(Nil, restp) instead of restp
atPos(tree.pos)(Apply(tree, Nil) setType tree.tpe.resultType)
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/DeVirtualize.scala b/src/compiler/scala/tools/nsc/typechecker/DeVirtualize.scala
index c473df5333..34ba6f6da9 100644
--- a/src/compiler/scala/tools/nsc/typechecker/DeVirtualize.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/DeVirtualize.scala
@@ -232,7 +232,7 @@ abstract class DeVirtualize /* extends InfoTransform with TypingTransformers {
val param = clazz.newMethod(clazz.pos, paramFieldName(clazz, index))
.setFlag(PROTECTED | LOCAL | DEFERRED | EXPANDEDNAME | SYNTHETIC | STABLE)
atPhase(ownPhase.next) {
- param.setInfo(PolyType(List(), tpe))
+ param.setInfo(NullaryMethodType(tpe))
}
param
}
@@ -294,7 +294,7 @@ abstract class DeVirtualize /* extends InfoTransform with TypingTransformers {
factory setInfo new PolyTypeCompleter(factory, clazz) {
private def copyType(tpe: Type): Type = tpe match {
case MethodType(formals, restpe) => MethodType(formals, copyType(restpe))
- case PolyType(List(), restpe) => PolyType(List(), copyType(restpe))
+ case NullaryMethodType(restpe) => NullaryMethodType(copyType(restpe))
case PolyType(_, _) => abort("bad case: "+tpe)
case _ => owner.thisType.memberType(abstractType(clazz))
}
@@ -394,7 +394,7 @@ abstract class DeVirtualize /* extends InfoTransform with TypingTransformers {
case (pt, i) =>
val pfield = cclazz.newMethod(cclazz.pos, paramFieldName(clazz, i))
.setFlag(PROTECTED | LOCAL | EXPANDEDNAME | SYNTHETIC | STABLE)
- .setInfo(PolyType(List(), pt))
+ .setInfo(NullaryMethodType(pt))
cclazz.info.decls enter pfield
atPos(factory.pos) {
DefDef(pfield, Ident(fixParamName(i)))
diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
index 6a708a873c..8ad6830e4c 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
@@ -114,6 +114,8 @@ trait Implicits {
private def containsError(tp: Type): Boolean = tp match {
case PolyType(tparams, restpe) =>
containsError(restpe)
+ case NullaryMethodType(restpe) =>
+ containsError(restpe)
case MethodType(params, restpe) =>
params.exists(_.tpe.isError) || containsError(restpe)
case _ =>
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index 84c770b553..15996923b2 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -175,7 +175,7 @@ trait Infer {
normalize(restpe)
case mt @ MethodType(params, restpe) if !restpe.isDependent =>
functionType(params map (_.tpe), normalize(restpe))
- case PolyType(List(), restpe) => // nullary method type
+ case NullaryMethodType(restpe) =>
normalize(restpe)
case ExistentialType(tparams, qtpe) =>
ExistentialType(tparams, normalize(qtpe))
@@ -350,6 +350,7 @@ trait Infer {
case tr: TypeRef => mtcheck(mt, tr)
case _ => lastChanceCheck(tp, pt)
}
+ case NullaryMethodType(restpe) => apply(restpe, pt)
case PolyType(_, restpe) => apply(restpe, pt)
case ExistentialType(_, qtpe) => apply(qtpe, pt)
case _ => argumentCheck(tp, pt)
@@ -367,7 +368,6 @@ trait Infer {
def lastChanceCheck(tp: Type, pt: Type) = tp <:< pt
override def apply(tp: Type, pt: Type): Boolean = tp match {
- case PolyType(tparams, restpe) => tparams.isEmpty && normSubType(restpe, pt)
case ExistentialType(_, _) => normalize(tp) <:< pt
case _ => super.apply(tp, pt)
}
@@ -659,7 +659,7 @@ trait Infer {
}
private[typechecker] def followApply(tp: Type): Type = tp match {
- case PolyType(List(), restp) =>
+ case NullaryMethodType(restp) =>
val restp1 = followApply(restp)
if (restp1 eq restp) tp else restp1
case _ =>
@@ -816,6 +816,8 @@ trait Infer {
else tryTupleApply
}
+ case NullaryMethodType(restpe) => // strip nullary method type, which used to be done by the polytype case below
+ isApplicable(undetparams, restpe, argtpes0, pt)
case PolyType(tparams, restpe) =>
val tparams1 = cloneSymbols(tparams)
isApplicable(tparams1 ::: undetparams, restpe.substSym(tparams, tparams1), argtpes0, pt)
@@ -860,18 +862,24 @@ trait Infer {
case et: ExistentialType =>
isAsSpecific(ftpe1.skolemizeExistential, ftpe2)
//et.withTypeVars(isAsSpecific(_, ftpe2))
+ case NullaryMethodType(res) =>
+ isAsSpecific(res, ftpe2)
case mt: MethodType if mt.isImplicit =>
isAsSpecific(ftpe1.resultType, ftpe2)
- case MethodType(params @ (x :: xs), _) =>
+ case MethodType(params, _) if params nonEmpty =>
var argtpes = params map (_.tpe)
if (isVarArgsList(params) && isVarArgsList(ftpe2.params))
argtpes = argtpes map (argtpe =>
if (isRepeatedParamType(argtpe)) argtpe.typeArgs.head else argtpe)
isApplicable(List(), ftpe2, argtpes, WildcardType)
+ case PolyType(tparams, NullaryMethodType(res)) =>
+ isAsSpecific(PolyType(tparams, res), ftpe2)
case PolyType(tparams, mt: MethodType) if mt.isImplicit =>
isAsSpecific(PolyType(tparams, mt.resultType), ftpe2)
- case PolyType(_, MethodType(params @ (x :: xs), _)) =>
+ case PolyType(_, MethodType(params, _)) if params nonEmpty =>
isApplicable(List(), ftpe2, params map (_.tpe), WildcardType)
+ // case NullaryMethodType(res) =>
+ // isAsSpecific(res, ftpe2)
case ErrorType =>
true
case _ =>
@@ -882,12 +890,25 @@ trait Infer {
et.withTypeVars(isAsSpecific(ftpe1, _))
case mt: MethodType =>
!mt.isImplicit || isAsSpecific(ftpe1, mt.resultType)
+ case NullaryMethodType(res) =>
+ isAsSpecific(ftpe1, res)
+ case PolyType(tparams, NullaryMethodType(res)) =>
+ isAsSpecific(ftpe1, PolyType(tparams, res))
case PolyType(tparams, mt: MethodType) =>
!mt.isImplicit || isAsSpecific(ftpe1, PolyType(tparams, mt.resultType))
case _ =>
isAsSpecificValueType(ftpe1, ftpe2, List(), List())
}
}
+ private def isAsSpecificValueType(tpe1: Type, tpe2: Type, undef1: List[Symbol], undef2: List[Symbol]): Boolean = (tpe1, tpe2) match {
+ case (PolyType(tparams1, rtpe1), _) =>
+ isAsSpecificValueType(rtpe1, tpe2, undef1 ::: tparams1, undef2)
+ case (_, PolyType(tparams2, rtpe2)) =>
+ isAsSpecificValueType(tpe1, rtpe2, undef1, undef2 ::: tparams2)
+ case _ =>
+ existentialAbstraction(undef1, tpe1) <:< existentialAbstraction(undef2, tpe2)
+ }
+
/*
def isStrictlyMoreSpecific(ftpe1: Type, ftpe2: Type): Boolean =
@@ -943,16 +964,6 @@ trait Infer {
case _ =>
false
}
-
- private def isAsSpecificValueType(tpe1: Type, tpe2: Type, undef1: List[Symbol], undef2: List[Symbol]): Boolean = (tpe1, tpe2) match {
- case (PolyType(tparams1, rtpe1), _) =>
- isAsSpecificValueType(rtpe1, tpe2, undef1 ::: tparams1, undef2)
- case (_, PolyType(tparams2, rtpe2)) =>
- isAsSpecificValueType(tpe1, rtpe2, undef1, undef2 ::: tparams2)
- case _ =>
- existentialAbstraction(undef1, tpe1) <:< existentialAbstraction(undef2, tpe2)
- }
-
/*
/** Is type `tpe1' a strictly better expression alternative than type `tpe2'?
*/
@@ -1120,7 +1131,7 @@ trait Infer {
if (targs eq null) {
if (!tree.tpe.isErroneous && !pt.isErroneous)
error(tree.pos, "polymorphic expression cannot be instantiated to expected type" +
- foundReqMsg(PolyType(undetparams, skipImplicit(tree.tpe)), pt))
+ foundReqMsg(polyType(undetparams, skipImplicit(tree.tpe)), pt))
} else {
new TreeTypeSubstituter(undetparams, targs).traverse(tree)
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index 775731df2b..9b27b35e82 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -578,7 +578,7 @@ trait Namers { self: Analyzer =>
def getterTypeCompleter(vd: ValDef) = mkTypeCompleter(vd) { sym =>
if (settings.debug.value) log("defining " + sym)
val tp = typeSig(vd)
- sym.setInfo(PolyType(List(), tp))
+ sym.setInfo(NullaryMethodType(tp))
if (settings.debug.value) log("defined " + sym)
validate(sym)
}
@@ -862,7 +862,7 @@ trait Namers { self: Analyzer =>
polyType(
tparamSyms, // deSkolemized symbols -- TODO: check that their infos don't refer to method args?
- if (vparamSymss.isEmpty) PolyType(List(), restpe) // nullary method type
+ if (vparamSymss.isEmpty) NullaryMethodType(restpe)
// vparamss refer (if they do) to skolemized tparams
else (vparamSymss :\ restpe) (makeMethodType))
}
@@ -907,7 +907,7 @@ trait Namers { self: Analyzer =>
resultPt = resultPt.resultType
}
resultPt match {
- case PolyType(List(), rtpe) => resultPt = rtpe
+ case NullaryMethodType(rtpe) => resultPt = rtpe
case MethodType(List(), rtpe) => resultPt = rtpe
case _ =>
}
@@ -1264,22 +1264,8 @@ trait Namers { self: Analyzer =>
}
result match {
case PolyType(tparams @ (tp :: _), _) if tp.owner.isTerm =>
- // ||
- // Adriaan: The added condition below is quite a hack. It seems that HK type parameters is relying
- // on a pass that forces all infos in the type to get everything right.
- // The problem is that the same pass causes cyclic reference errors in
- // test pos/cyclics.scala. It turned out that deSkolemize is run way more often than necessary,
- // running it only when needed fixes the cyclic reference errors.
- // But correcting deSkolemize broke HK types, because we don't do the traversal anymore.
- // For the moment I made a special hack to do the traversal if we have HK type parameters.
- // Maybe it's not a hack, then we need to document it better. But ideally, we should find
- // a way to deal with HK types that's not dependent on accidental side
- // effects like this.
- // tparams.exists(!_.typeParams.isEmpty)) =>
new DeSkolemizeMap(tparams) mapOver result
case _ =>
-// println("not skolemizing "+result+" in "+context.owner)
-// new DeSkolemizeMap(List()) mapOver result
result
}
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index adc7813b9c..df8ec9c762 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -66,7 +66,7 @@ abstract class RefChecks extends InfoTransform {
sym.setFlag(LAZY | ACCESSOR)
}
}
- PolyType(List(), tp)
+ NullaryMethodType(tp)
} else tp
}
@@ -244,12 +244,12 @@ abstract class RefChecks extends InfoTransform {
}
def overridesType(tp1: Type, tp2: Type): Boolean = (tp1.normalize, tp2.normalize) match {
- case (MethodType(List(), rtp1), PolyType(List(), rtp2)) =>
+ case (MethodType(List(), rtp1), NullaryMethodType(rtp2)) =>
rtp1 <:< rtp2
- case (PolyType(List(), rtp1), MethodType(List(), rtp2)) =>
+ case (NullaryMethodType(rtp1), MethodType(List(), rtp2)) =>
rtp1 <:< rtp2
case (TypeRef(_, sym, _), _) if (sym.isModuleClass) =>
- overridesType(PolyType(List(), tp1), tp2)
+ overridesType(NullaryMethodType(tp1), tp2)
case _ =>
tp1 <:< tp2
}
@@ -753,6 +753,8 @@ abstract class RefChecks extends InfoTransform {
validateVariance(hi, variance)
case MethodType(formals, result) =>
validateVariance(result, variance)
+ case NullaryMethodType(result) =>
+ validateVariance(result, variance)
case PolyType(tparams, result) =>
// type parameters will be validated separately, because they are defined explicitly.
validateVariance(result, variance)
@@ -1006,7 +1008,7 @@ abstract class RefChecks extends InfoTransform {
if (!sym.allOverriddenSymbols.isEmpty) {
val factory = sym.owner.newMethod(sym.pos, sym.name.toTermName)
.setFlag(sym.flags | STABLE).resetFlag(MODULE)
- .setInfo(PolyType(List(), sym.moduleClass.tpe))
+ .setInfo(NullaryMethodType(sym.moduleClass.tpe))
sym.owner.info.decls.enter(factory)
val ddef =
atPhase(phase.next) {
@@ -1043,7 +1045,7 @@ abstract class RefChecks extends InfoTransform {
sym.resetFlag(MODULE | FINAL | CASE)
sym.setFlag(LAZY | ACCESSOR | SYNTHETIC)
- sym.setInfo(PolyType(List(), sym.tpe))
+ sym.setInfo(NullaryMethodType(sym.tpe))
sym setFlag (lateMETHOD | STABLE)
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
index 3e8f7bd2c7..6f3bb9e976 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
@@ -103,7 +103,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
var superAccTpe = clazz.thisType.memberType(sym)
if (sym.isModule && !sym.isMethod) {
// the super accessor always needs to be a method. See #231
- superAccTpe = PolyType(List(), superAccTpe)
+ superAccTpe = NullaryMethodType(superAccTpe)
}
superAcc.setInfo(superAccTpe.cloneInfo(superAcc))
//println("creating super acc "+superAcc+":"+superAcc.tpe)//DEBUG
diff --git a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
index 2d544ba1d1..03b080398f 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
@@ -86,12 +86,12 @@ trait SyntheticMethods extends ast.TreeDSL {
import CODE._
def productPrefixMethod: Tree = typer.typed {
- val method = syntheticMethod(nme.productPrefix, 0, sym => PolyType(Nil, StringClass.tpe))
+ val method = syntheticMethod(nme.productPrefix, 0, sym => NullaryMethodType(StringClass.tpe))
DEF(method) === LIT(clazz.name.decode)
}
def productArityMethod(nargs: Int): Tree = {
- val method = syntheticMethod(nme.productArity, 0, sym => PolyType(Nil, IntClass.tpe))
+ val method = syntheticMethod(nme.productArity, 0, sym => NullaryMethodType(IntClass.tpe))
typer typed { DEF(method) === LIT(nargs) }
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 3337584420..19fc981035 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -568,6 +568,7 @@ trait Typers extends Modes {
case ExistentialType(_, tpe1) => isNarrowable(tpe1)
case AnnotatedType(_, tpe1, _) => isNarrowable(tpe1)
case PolyType(_, tpe1) => isNarrowable(tpe1)
+ case NullaryMethodType(tpe1) => isNarrowable(tpe1)
case _ => !phase.erasedTypes
}
@@ -702,7 +703,7 @@ trait Typers extends Modes {
case OverloadedType(pre, alts) if !inFunMode(mode) => // (1)
inferExprAlternative(tree, pt)
adapt(tree, mode, pt, original)
- case PolyType(List(), restpe) => // (2)
+ case NullaryMethodType(restpe) => // (2)
adapt(tree setType restpe, mode, pt, original)
case TypeRef(_, ByNameParamClass, List(arg))
if ((mode & EXPRmode) != 0) => // (2)
@@ -1591,6 +1592,8 @@ trait Typers extends Modes {
if (meth.owner.isStructuralRefinement && meth.allOverriddenSymbols.isEmpty && !(meth.isPrivate || meth.hasAccessBoundary)) {
val tp: Type = meth.tpe match {
case mt: MethodType => mt
+ case NullaryMethodType(res) => res
+ // TODO_NMT: drop NullaryMethodType from resultType?
case pt: PolyType => pt.resultType
case _ => NoType
}
@@ -1624,7 +1627,7 @@ trait Typers extends Modes {
case tpt: Tree =>
val alias = enclClass.newAliasType(useCase.pos, name.toTypeName)
val tparams = cloneSymbols(tpt.tpe.typeSymbol.typeParams, alias)
- alias setInfo polyType(tparams, appliedType(tpt.tpe, tparams map (_.tpe)))
+ alias setInfo typeFun(tparams, appliedType(tpt.tpe, tparams map (_.tpe)))
context.scope.enter(alias)
case _ =>
}
@@ -2175,6 +2178,7 @@ trait Typers extends Modes {
}
def doTypedApply(tree: Tree, fun0: Tree, args: List[Tree], mode: Int, pt: Type): Tree = {
+ // TODO_NMT: check the assumption that args nonEmpty
var fun = fun0
if (fun.hasSymbol && fun.symbol.isOverloaded) {
// remove alternatives with wrong number of parameters without looking at types.
@@ -3148,7 +3152,7 @@ trait Typers extends Modes {
val expr2 = Function(List(), expr1) setPos expr1.pos
new ChangeOwnerTraverser(context.owner, expr2.symbol).traverse(expr2)
typed1(expr2, mode, pt)
- case PolyType(List(), restpe) =>
+ case NullaryMethodType(restpe) =>
val expr2 = Function(List(), expr1) setPos expr1.pos
new ChangeOwnerTraverser(context.owner, expr2.symbol).traverse(expr2)
typed1(expr2, mode, pt)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Variances.scala b/src/compiler/scala/tools/nsc/typechecker/Variances.scala
index 4ad5c9057f..e29d96e663 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Variances.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Variances.scala
@@ -78,6 +78,8 @@ trait Variances {
varianceInTypes(parents)(tparam) & varianceInSyms(defs.toList)(tparam)
case MethodType(params, restpe) =>
flip(varianceInSyms(params)(tparam)) & varianceInType(restpe)(tparam)
+ case NullaryMethodType(restpe) =>
+ varianceInType(restpe)(tparam)
case PolyType(tparams, restpe) =>
flip(varianceInSyms(tparams)(tparam)) & varianceInType(restpe)(tparam)
case ExistentialType(tparams, restpe) =>
diff --git a/src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala b/src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala
index 5151f1eeee..2df538fe85 100644
--- a/src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala
+++ b/src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala
@@ -373,9 +373,10 @@ abstract class CPSAnnotationChecker extends CPSUtils {
transChildrenInOrder(tree, tpe, qual::(transArgList(fun, args).flatten), Nil)
case TypeApply(fun @ Select(qual, name), args) if fun.isTyped =>
+ def stripNullaryMethodType(tp: Type) = tp match { case NullaryMethodType(restpe) => restpe case tp => tp }
vprintln("[checker] checking select apply " + tree + "/" + tpe)
- transChildrenInOrder(tree, tpe, List(qual, fun), Nil)
+ transChildrenInOrder(tree, stripNullaryMethodType(tpe), List(qual, fun), Nil)
case Apply(fun, args) if fun.isTyped =>
@@ -406,7 +407,7 @@ abstract class CPSAnnotationChecker extends CPSUtils {
// we have to do it here so we don't lose the cps information (wouldn't trigger our
// adapt and there is no Apply/TypeApply created)
tpe match {
- case PolyType(List(), restpe) =>
+ case NullaryMethodType(restpe) =>
//println("yep: " + restpe + "," + restpe.getClass)
transChildrenInOrder(tree, restpe, List(qual), Nil)
case _ : PolyType => tpe
diff --git a/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala b/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala
index 07a9e5fed5..78cc8f7ff7 100644
--- a/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala
+++ b/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala
@@ -50,8 +50,8 @@ abstract class SelectiveCPSTransform extends PluginComponent with
def transformCPSType(tp: Type): Type = { // TODO: use a TypeMap? need to handle more cases?
tp match {
case PolyType(params,res) => PolyType(params, transformCPSType(res))
- case MethodType(params,res) =>
- MethodType(params, transformCPSType(res))
+ case NullaryMethodType(res) => NullaryMethodType(transformCPSType(res))
+ case MethodType(params,res) => MethodType(params, transformCPSType(res))
case TypeRef(pre, sym, args) => TypeRef(pre, sym, args.map(transformCPSType(_)))
case _ =>
getExternalAnswerTypeAnn(tp) match {
diff --git a/src/library/scala/reflect/Print.scala b/src/library/scala/reflect/Print.scala
index a84e024c36..1c51a8b2b1 100644
--- a/src/library/scala/reflect/Print.scala
+++ b/src/library/scala/reflect/Print.scala
@@ -101,6 +101,8 @@ object Print extends Function1[Any, String] {
"[" + Print(lo) + " ... " + Print(hi) + "]"
case reflect.MethodType(formals, resultType) =>
formals.map(Print).mkString("(", ", ", ")") + " => " + Print(resultType)
+ case reflect.NullaryMethodType(resultType) =>
+ " => " + Print(resultType)
case reflect.PolyType(typeParams, typeBounds, resultType) =>
val z = (typeParams, typeBounds).zipped map ((tp, tb) => "[" + Print(tb._1) + " :> " + Print(tp) + " :> " + Print(tb._2) + "]")
z.mkString("[", ", ", "]") + " -> " + Print(resultType)
diff --git a/src/library/scala/reflect/Type.scala b/src/library/scala/reflect/Type.scala
index 029bb3966e..0ec0b77fad 100644
--- a/src/library/scala/reflect/Type.scala
+++ b/src/library/scala/reflect/Type.scala
@@ -49,6 +49,8 @@ case class TypeBounds(lo: Type, hi: Type) extends Type
* <code>(formals1 ... formalsn) restpe</code> */
case class MethodType(formals: List[Symbol], restpe: Type) extends Type
+/** This type is required by the compiler and <b>should not be used in client code</b>. */
+case class NullaryMethodType(resultType: Type) extends Type
/** This type is required by the compiler and <b>should not be used in client code</b>. */
case class PolyType(typeParams: List[Symbol], typeBounds: List[(Type, Type)], resultType: Type) extends Type
@@ -71,5 +73,6 @@ extends MethodType(formals, restpe)
case reflect.AppliedType(tpe, args) =>
case reflect.TypeBounds(lo, hi) =>
case reflect.MethodType(formals, restpe) => //can also be ImplicitMethodType
+ case reflect.NullaryMethodType(restpe) =>
case reflect.PolyType(typeParams, typeBounds, resultType) =>
*/
diff --git a/src/library/scala/reflect/generic/Types.scala b/src/library/scala/reflect/generic/Types.scala
index 17e19715d7..6dcd90e66c 100755
--- a/src/library/scala/reflect/generic/Types.scala
+++ b/src/library/scala/reflect/generic/Types.scala
@@ -69,6 +69,9 @@ trait Types { self: Universe =>
type MethodType <: Type
val MethodType: MethodTypeExtractor
+ type NullaryMethodType <: Type
+ val NullaryMethodType: NullaryMethodTypeExtractor
+
type PolyType <: Type
val PolyType: PolyTypeExtractor
@@ -132,6 +135,11 @@ trait Types { self: Universe =>
def unapply(tpe: MethodType): Option[(List[Symbol], Type)]
}
+ abstract class NullaryMethodTypeExtractor {
+ def apply(resultType: Type): NullaryMethodType
+ def unapply(tpe: NullaryMethodType): Option[(Type)]
+ }
+
abstract class PolyTypeExtractor {
def apply(typeParams: List[Symbol], resultType: Type): PolyType
def unapply(tpe: PolyType): Option[(List[Symbol], Type)]
diff --git a/src/library/scala/reflect/generic/UnPickler.scala b/src/library/scala/reflect/generic/UnPickler.scala
index 7b7c34a767..86b73cf5fd 100755
--- a/src/library/scala/reflect/generic/UnPickler.scala
+++ b/src/library/scala/reflect/generic/UnPickler.scala
@@ -281,7 +281,7 @@ abstract class UnPickler {
sym
case MODULEsym =>
- val clazz = at(inforef, readType).typeSymbol
+ val clazz = at(inforef, () => readType()).typeSymbol // after the NMT_TRANSITION period, we can leave off the () => ... ()
if (isModuleRoot) moduleRoot
else {
val m = owner.newModule(name, clazz)
@@ -298,8 +298,13 @@ abstract class UnPickler {
})
}
- /** Read a type */
- protected def readType(): Type = {
+ /** Read a type
+ *
+ * @param forceProperType is used to ease the transition to NullaryMethodTypes (commentmarker: NMT_TRANSITION)
+ * the flag say that a type of kind * is expected, so that PolyType(tps, restpe) can be disambiguated to PolyType(tps, NullaryMethodType(restpe))
+ * (if restpe is not a ClassInfoType, a MethodType or a NullaryMethodType, which leaves TypeRef/SingletonType -- the latter would make the polytype a type constructor)
+ */
+ protected def readType(forceProperType: Boolean = false): Type = {
val tag = readByte()
val end = readNat() + readIndex
(tag: @switch) match {
@@ -341,7 +346,19 @@ abstract class UnPickler {
case POLYtpe =>
val restpe = readTypeRef()
val typeParams = until(end, readSymbolRef)
- PolyType(typeParams, restpe)
+ if(typeParams nonEmpty) {
+ // NMT_TRANSITION: old class files denoted a polymorphic nullary method as PolyType(tps, restpe), we now require PolyType(tps, NullaryMethodType(restpe))
+ // when a type of kind * is expected (forceProperType is true), we know restpe should be wrapped in a NullaryMethodType (if it wasn't suitably wrapped yet)
+ def transitionNMT(restpe: Type) = {
+ val resTpeCls = restpe.getClass.toString // what's uglier than isInstanceOf? right! -- isInstanceOf does not work since the concrete types are defined in the compiler (not in scope here)
+ if(forceProperType /*&& pickleformat < 2.9 */ && !(resTpeCls.endsWith("MethodType"))) { assert(!resTpeCls.contains("ClassInfoType"))
+ NullaryMethodType(restpe) }
+ else restpe
+ }
+ PolyType(typeParams, transitionNMT(restpe))
+ }
+ else
+ NullaryMethodType(restpe)
case EXISTENTIALtpe =>
val restpe = readTypeRef()
ExistentialType(until(end, readSymbolRef), restpe)
@@ -352,7 +369,7 @@ abstract class UnPickler {
typeRef = readNat()
s
} else NoSymbol // selfsym can go.
- val tp = at(typeRef, readType)
+ val tp = at(typeRef, () => readType(forceProperType)) // NMT_TRANSITION
val annots = until(end, readAnnotationRef)
if (selfsym == NoSymbol) AnnotatedType(annots, tp, selfsym)
else tp
@@ -739,7 +756,7 @@ abstract class UnPickler {
/* Read a reference to a pickled item */
protected def readNameRef(): Name = at(readNat(), readName)
protected def readSymbolRef(): Symbol = at(readNat(), readSymbol)
- protected def readTypeRef(): Type = at(readNat(), readType)
+ protected def readTypeRef(): Type = at(readNat(), () => readType()) // after the NMT_TRANSITION period, we can leave off the () => ... ()
protected def readConstantRef(): Constant = at(readNat(), readConstant)
protected def readAnnotationRef(): AnnotationInfo = at(readNat(), readAnnotation)
protected def readModifiersRef(): Modifiers = at(readNat(), readModifiers)
diff --git a/test/files/lib/scalacheck.jar.desired.sha1 b/test/files/lib/scalacheck.jar.desired.sha1
index b7c059680a..cdbdc53af5 100644
--- a/test/files/lib/scalacheck.jar.desired.sha1
+++ b/test/files/lib/scalacheck.jar.desired.sha1
@@ -1 +1 @@
-4afb204d3626d91d175a25dce465336ef804d6d4 ?scalacheck.jar
+77dca656258fe983ec64461860ab1ca0f7e2fd65 ?scalacheck.jar
diff --git a/test/files/pos/t2741/2741-1.scala b/test/files/pos/t2741/2741-1.scala
deleted file mode 100644
index 91c120ec1b..0000000000
--- a/test/files/pos/t2741/2741-1.scala
+++ /dev/null
@@ -1,13 +0,0 @@
-sealed trait Kleisli[M[_], A, B]
-
-trait PartialApplyKA[T[_[_], _, _], M[_], A] {
- type Apply[B] = T[M, A, B]
-}
-
-trait MA[M[_], A]
-
-trait MAs {
- val a: MA[PartialApplyKA[Kleisli, List, String]#Apply, Int] = null
-}
-
-object Scalaz extends MAs
diff --git a/test/files/pos/t2741/2741-2.scala b/test/files/pos/t2741/2741-2.scala
deleted file mode 100644
index 41f6a64260..0000000000
--- a/test/files/pos/t2741/2741-2.scala
+++ /dev/null
@@ -1,5 +0,0 @@
-// object Test compiles jointly, but not separately.
-object Test {
- import Scalaz._
- Scalaz.a
-} \ No newline at end of file