aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2013-09-27 22:10:45 +0200
committerMartin Odersky <odersky@gmail.com>2013-09-28 11:43:43 +0200
commit0c582b883971fd89476244aa6905be95da7e79d0 (patch)
tree079efc09d1e5b53b1e258b565dbb15c8b14954f7 /src/dotty/tools/dotc
parentfcb68309c2760a6797b0a9ec23722808060e9aa1 (diff)
downloaddotty-0c582b883971fd89476244aa6905be95da7e79d0.tar.gz
dotty-0c582b883971fd89476244aa6905be95da7e79d0.tar.bz2
dotty-0c582b883971fd89476244aa6905be95da7e79d0.zip
Several bug fixes to typer and classfile reader.
In particular, changed internal representation of Java constructors and changed treatment of parent constructors in templates.
Diffstat (limited to 'src/dotty/tools/dotc')
-rw-r--r--src/dotty/tools/dotc/ast/CheckTrees.scala4
-rw-r--r--src/dotty/tools/dotc/ast/Desugar.scala4
-rw-r--r--src/dotty/tools/dotc/ast/TreeInfo.scala13
-rw-r--r--src/dotty/tools/dotc/ast/TypedTrees.scala4
-rw-r--r--src/dotty/tools/dotc/core/Denotations.scala6
-rw-r--r--src/dotty/tools/dotc/core/Flags.scala5
-rw-r--r--src/dotty/tools/dotc/core/TypeComparer.scala10
-rw-r--r--src/dotty/tools/dotc/core/Types.scala9
-rw-r--r--src/dotty/tools/dotc/core/pickling/ClassfileParser.scala39
-rw-r--r--src/dotty/tools/dotc/parsing/Parsers.scala7
-rw-r--r--src/dotty/tools/dotc/typer/Applications.scala2
-rw-r--r--src/dotty/tools/dotc/typer/Inferencing.scala2
-rw-r--r--src/dotty/tools/dotc/typer/Namer.scala10
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala6
14 files changed, 87 insertions, 34 deletions
diff --git a/src/dotty/tools/dotc/ast/CheckTrees.scala b/src/dotty/tools/dotc/ast/CheckTrees.scala
index 92a069a76..b99548162 100644
--- a/src/dotty/tools/dotc/ast/CheckTrees.scala
+++ b/src/dotty/tools/dotc/ast/CheckTrees.scala
@@ -206,7 +206,7 @@ object CheckTrees {
check(args.head.isInstanceOf[SeqLiteral])
case nme.unapply =>
val rtp = funtpe.resultType
- val rsym = rtp.dealias.typeSymbol
+ val rsym = rtp.dealiasedTypeSymbol
if (rsym == defn.BooleanClass)
check(args.isEmpty)
else {
@@ -216,7 +216,7 @@ object CheckTrees {
optionArg.typeArgs match {
case Nil =>
optionArg :: Nil
- case tupleArgs if defn.TupleClasses contains optionArg.dealias.typeSymbol =>
+ case tupleArgs if defn.TupleClasses contains optionArg.dealiasedTypeSymbol =>
tupleArgs
}
case _ =>
diff --git a/src/dotty/tools/dotc/ast/Desugar.scala b/src/dotty/tools/dotc/ast/Desugar.scala
index f58df1739..31154b2ef 100644
--- a/src/dotty/tools/dotc/ast/Desugar.scala
+++ b/src/dotty/tools/dotc/ast/Desugar.scala
@@ -105,11 +105,11 @@ object desugar {
case _ =>
rhs
}
- if (mods is PrivateLocalParamAccessor) {
+ if (mods is PrivateLocalParam) {
val tparam = cpy.TypeDef(tdef,
mods &~ PrivateLocal | ExpandedName, name.expandedName(ctx.owner), rhs1, tdef.tparams)
val alias = cpy.TypeDef(tdef,
- Modifiers(PrivateLocal | Synthetic), name, refOfDef(tparam))
+ Modifiers(PrivateLocalParamAccessor | Synthetic), name, refOfDef(tparam))
Thicket(tparam, alias)
}
else cpy.TypeDef(tdef, mods, name, rhs1)
diff --git a/src/dotty/tools/dotc/ast/TreeInfo.scala b/src/dotty/tools/dotc/ast/TreeInfo.scala
index 665fbec89..e8303e6b8 100644
--- a/src/dotty/tools/dotc/ast/TreeInfo.scala
+++ b/src/dotty/tools/dotc/ast/TreeInfo.scala
@@ -67,13 +67,20 @@ trait TreeInfo[T >: Untyped] { self: Trees.Instance[T] =>
* <init>(x$2, x$1)
* }
*/
- def methPart(tree: Tree): Tree = tree match {
- case Apply(fn, _) => methPart(fn)
+ def methPart(tree: Tree): Tree = stripApply(tree) match {
case TypeApply(fn, _) => methPart(fn)
- case AppliedTypeTree(fn, _) => methPart(fn)
+ case AppliedTypeTree(fn, _) => methPart(fn) // !!! should not be needed
case Block(stats, expr) => methPart(expr)
case _ => tree
}
+
+ /** If this is an application, its function part, stripping all
+ * Apply nodes (but leaving TypeApply nodes in). Otherwise the tree itself.
+ */
+ def stripApply(tree: Tree): Tree = tree match {
+ case Apply(fn, _) => stripApply(fn)
+ case _ => tree
+ }
/** The number of arguments in an application */
def numArgs(tree: Tree): Int = tree match {
diff --git a/src/dotty/tools/dotc/ast/TypedTrees.scala b/src/dotty/tools/dotc/ast/TypedTrees.scala
index a126108aa..79e54fccb 100644
--- a/src/dotty/tools/dotc/ast/TypedTrees.scala
+++ b/src/dotty/tools/dotc/ast/TypedTrees.scala
@@ -255,9 +255,9 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
val selfType =
if (cls.classInfo.selfInfo ne NoType) ValDef(ctx.newSelfSym(cls))
else EmptyValDef
- def isOwnTypeParamAccessor(stat: Tree) =
+ def isOwnTypeParam(stat: Tree) =
(stat.symbol is TypeParam) && stat.symbol.owner == cls
- val bodyTypeParams = body filter isOwnTypeParamAccessor map (_.symbol)
+ val bodyTypeParams = body filter isOwnTypeParam map (_.symbol)
val newTypeParams =
for (tparam <- cls.typeParams if !(bodyTypeParams contains tparam))
yield TypeDef(tparam)
diff --git a/src/dotty/tools/dotc/core/Denotations.scala b/src/dotty/tools/dotc/core/Denotations.scala
index 89c0b3861..74b669a77 100644
--- a/src/dotty/tools/dotc/core/Denotations.scala
+++ b/src/dotty/tools/dotc/core/Denotations.scala
@@ -397,13 +397,13 @@ object Denotations {
def orElse(that: => SingleDenotation) = if (this.exists) this else that
def altsWith(p: Symbol => Boolean): List[SingleDenotation] =
- if (p(symbol)) this :: Nil else Nil
+ if (exists && p(symbol)) this :: Nil else Nil
def suchThat(p: Symbol => Boolean): SingleDenotation =
- if (p(symbol)) this else NoDenotation
+ if (exists && p(symbol)) this else NoDenotation
def hasAltWith(p: SingleDenotation => Boolean): Boolean =
- p(this)
+ exists && p(this)
def accessibleFrom(pre: Type, superAccess: Boolean)(implicit ctx: Context): Denotation =
if (symbol isAccessibleFrom (pre, superAccess)) this else NoDenotation
diff --git a/src/dotty/tools/dotc/core/Flags.scala b/src/dotty/tools/dotc/core/Flags.scala
index 229d71568..0c433ecc5 100644
--- a/src/dotty/tools/dotc/core/Flags.scala
+++ b/src/dotty/tools/dotc/core/Flags.scala
@@ -235,6 +235,8 @@ object Flags {
* or an accessor of such a field.
*/
final val ParamAccessor = commonFlag(14, "<paramaccessor>")
+ final val TermParamAccessor = ParamAccessor.toTermFlags
+ final val TypeParamAccessor = ParamAccessor.toTypeFlags
/** A value or class implementing a module */
final val Module = commonFlag(15, "module")
@@ -471,6 +473,9 @@ object Flags {
/** A private parameter accessor */
final val PrivateLocalParamAccessor = allOf(Private, Local, ParamAccessor)
+ /** A private parameter */
+ final val PrivateLocalParam = allOf(Private, Local, Param)
+
/** A local parameter */
final val ParamAndLocal = allOf(Param, Local)
diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala
index 588756db4..1d853c44d 100644
--- a/src/dotty/tools/dotc/core/TypeComparer.scala
+++ b/src/dotty/tools/dotc/core/TypeComparer.scala
@@ -220,10 +220,9 @@ class TypeComparer(initctx: Context) extends DotClass {
case tp2: RefinedType =>
isSubType(tp1, tp2.parent) && (
tp2.refinedName == nme.WILDCARD
- || (tp1 isRef NothingClass)
- || (tp1 isRef NullClass)
|| tp1.member(tp2.refinedName).hasAltWith(alt =>
- isSubType(alt.info, tp2.refinedInfo)))
+ isSubType(alt.info, tp2.refinedInfo))
+ || fourthTry(tp1, tp2))
case AndType(tp21, tp22) =>
isSubType(tp1, tp21) && isSubType(tp1, tp22)
case OrType(tp21, tp22) =>
@@ -280,7 +279,7 @@ class TypeComparer(initctx: Context) extends DotClass {
def fourthTry(tp1: Type, tp2: Type): Boolean = tp1 match {
case tp1: TypeRef =>
((tp1.symbol eq NothingClass)
- || (tp1.symbol eq NullClass) && tp2.dealias.typeSymbol.isNonValueClass
+ || (tp1.symbol eq NullClass) && tp2.dealiasedTypeSymbol.isNonValueClass
|| (tp1.info match {
case TypeBounds(lo1, hi1) =>
isSubType(hi1, tp2) ||
@@ -289,6 +288,8 @@ class TypeComparer(initctx: Context) extends DotClass {
}))
case tp1: SingletonType =>
isSubType(tp1.underlying, tp2)
+ case tp1: ExprType =>
+ isSubType(tp1.underlying, tp2)
case tp1: RefinedType =>
isSubType(tp1.parent, tp2)
case AndType(tp11, tp12) =>
@@ -544,7 +545,6 @@ class ExplainingTypeComparer(initctx: Context) extends TypeComparer(initctx) {
private val b = new StringBuilder
def traceIndented[T](str: String)(op: => T): T = {
- assert(str != "<notype> <:< Int")
indent += 2
b append "\n" append (" " * indent) append "==> " append str
val res = op
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index ee76f0dc7..59ac01819 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -214,6 +214,15 @@ object Types {
case _ => NoSymbol
}
+ /** The type symbol associated with the type, skipping alises */
+ final def dealiasedTypeSymbol(implicit ctx: Context): Symbol = this match {
+ case tp: TermRef => NoSymbol
+ case tp: ClassInfo => tp.cls
+ case ThisType(cls) => cls
+ case tp: TypeProxy => tp.underlying.dealiasedTypeSymbol
+ case _ => NoSymbol
+ }
+
/** The least class or trait of which this type is a subtype, or
* NoSymbol if none exists (either because this type is not a
* value type, or because superclasses are ambiguous).
diff --git a/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala b/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala
index f640c3d67..b65fc55bb 100644
--- a/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala
+++ b/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala
@@ -164,6 +164,7 @@ class ClassfileParser(
}
val memberCompleter = new LazyType {
+
def complete(denot: SymDenotation): Unit = {
val oldbp = in.bp
try {
@@ -172,19 +173,35 @@ class ClassfileParser(
val jflags = in.nextChar
val isEnum = (jflags & JAVA_ACC_ENUM) != 0
val name = pool.getName(in.nextChar)
- val info = pool.getType(in.nextChar)
+ val isConstructor = name eq nme.CONSTRUCTOR
+
+ /** Strip leading outer param from constructor.
+ * Todo: Also strip trailing access tag for private inner constructors?
+ */
+ 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)
+ case _ =>
+ }
- denot.info = if (isEnum) ConstantType(Constant(sym)) else info
- if (name == nme.CONSTRUCTOR)
- // if this is a non-static inner class, remove the explicit outer parameter
- innerClasses.get(currentClassName) match {
- case Some(entry) if !isStatic(entry.jflags) =>
- val mt @ MethodType(paramnames, paramtypes) = info
- denot.info = mt.derivedMethodType(paramnames.tail, paramtypes.tail, mt.resultType)
- case _ =>
- }
+ /** Make return type of constructor be the enclosing class type,
+ * and make constructor type polymorphic in the type parameters of the class
+ */
+ def normalizeConstructorInfo() = {
+ val mt @ MethodType(paramnames, paramtypes) = denot.info
+ val typeParams = classRoot.typeParams
+ val rt = classRoot.typeConstructor appliedTo (typeParams map (_.symRef))
+ denot.info = PolyType.fromSymbols(typeParams,
+ mt.derivedMethodType(paramnames, paramtypes, rt))
+ }
+
+ denot.info = pool.getType(in.nextChar)
+ if (isEnum) denot.info = ConstantType(Constant(sym))
+ if (isConstructor) stripOuterParamFromConstructor()
setPrivateWithin(denot, jflags)
- denot.info = depoly(parseAttributes(sym, info), denot)
+ denot.info = depoly(parseAttributes(sym, denot.info), denot)
+ if (isConstructor) normalizeConstructorInfo()
if ((denot is Flags.Method) && (jflags & JAVA_ACC_VARARGS) != 0)
denot.info = arrayToRepeated(denot.info)
diff --git a/src/dotty/tools/dotc/parsing/Parsers.scala b/src/dotty/tools/dotc/parsing/Parsers.scala
index b1d314d7e..57356f305 100644
--- a/src/dotty/tools/dotc/parsing/Parsers.scala
+++ b/src/dotty/tools/dotc/parsing/Parsers.scala
@@ -1401,7 +1401,12 @@ object Parsers {
}
/** Wrap annotation or constructor in New(...).<init> */
- def wrapNew(tpt: Tree) = Select(New(tpt), nme.CONSTRUCTOR)
+ def wrapNew(tpt: Tree) = tpt match {
+ case AppliedTypeTree(tpt1, targs) =>
+ TypeApply(Select(New(tpt1), nme.CONSTRUCTOR), targs)
+ case _ =>
+ Select(New(tpt), nme.CONSTRUCTOR)
+ }
/** Adjust start of annotation or constructor to position of preceding @ or new */
def adjustStart(start: Offset)(tree: Tree): Tree = {
diff --git a/src/dotty/tools/dotc/typer/Applications.scala b/src/dotty/tools/dotc/typer/Applications.scala
index bf49091ec..673791d8d 100644
--- a/src/dotty/tools/dotc/typer/Applications.scala
+++ b/src/dotty/tools/dotc/typer/Applications.scala
@@ -475,7 +475,7 @@ trait Applications extends Compatibility { self: Typer =>
val qual1 = adapt(qual, new SelectionProto(name, proto))
if (qual1.tpe.isError) qual1
else {
- assert(qual1 ne qual)
+ assert(qual1 ne qual, s"$qual1 : ${qual1.tpe}")
typedApply(
cpy.Apply(tree,
cpy.Select(fun1, untpd.TypedSplice(qual1), name),
diff --git a/src/dotty/tools/dotc/typer/Inferencing.scala b/src/dotty/tools/dotc/typer/Inferencing.scala
index 2137981e7..c514699a3 100644
--- a/src/dotty/tools/dotc/typer/Inferencing.scala
+++ b/src/dotty/tools/dotc/typer/Inferencing.scala
@@ -153,7 +153,7 @@ object Inferencing {
case tp: TypeRef if tp.symbol.isClass =>
checkStable(tp.prefix, pos)
tp.symbol.asClass
- case _: RefinedType | _: TypeVar | _: AnnotatedType =>
+ case /* _: RefinedType |*/ _: TypeVar | _: AnnotatedType =>
checkClassTypeWithStablePrefix(tp.asInstanceOf[TypeProxy].underlying, pos)
case _ =>
ctx.error(i"$tp is not a class type", pos)
diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala
index a803903bb..e9eb7df0b 100644
--- a/src/dotty/tools/dotc/typer/Namer.scala
+++ b/src/dotty/tools/dotc/typer/Namer.scala
@@ -13,6 +13,7 @@ import util.SourcePosition
import collection.mutable
import annotation.tailrec
import ErrorReporting._
+import tpd.ListOfTreeDecorator
import language.implicitConversions
trait NamerContextOps { this: Context =>
@@ -296,8 +297,13 @@ class Namer { typer: Typer =>
def classDefSig(cdef: TypeDef, cls: ClassSymbol)(implicit ctx: Context): Type = {
//todo: normalize parents, so that all mixins extend superclass
def parentType(constr: untpd.Tree): Type = {
- val Trees.Select(Trees.New(tpt), _) = methPart(constr)
- val ptype = typedAheadType(tpt).tpe
+ val (core, targs) = stripApply(constr) match {
+ case TypeApply(core, targs) => (core, targs)
+ case core => (core, Nil)
+ }
+ val Select(New(tpt), _) = core
+ val targs1 = targs map (typedAheadType(_))
+ val ptype = typedAheadType(tpt).tpe appliedTo targs1.tpes
if (ptype.uninstantiatedTypeParams.isEmpty) ptype
else typedAheadExpr(constr).tpe
}
diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala
index 0c33aa026..21ebc196a 100644
--- a/src/dotty/tools/dotc/typer/Typer.scala
+++ b/src/dotty/tools/dotc/typer/Typer.scala
@@ -120,7 +120,11 @@ class Typer extends Namer with Applications with Implicits {
alts foreach (_.isAccessibleFrom(pre, superAccess, whyNot))
ctx.error(i"$what cannot be accessed in $where.$whyNot")
ErrorType
- } else tpe withDenot d
+ }
+ else if (d.symbol is TypeParamAccessor) // always dereference type param accessors
+ checkAccessible(d.info.bounds.hi, superAccess, pos)
+ else
+ tpe withDenot d
case _ =>
tpe
}