aboutsummaryrefslogtreecommitdiff
path: root/compiler/src/dotty/tools/dotc/core
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/src/dotty/tools/dotc/core')
-rw-r--r--compiler/src/dotty/tools/dotc/core/Definitions.scala4
-rw-r--r--compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala52
-rw-r--r--compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala36
3 files changed, 61 insertions, 31 deletions
diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala
index a97589d73..eee6ba785 100644
--- a/compiler/src/dotty/tools/dotc/core/Definitions.scala
+++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala
@@ -10,7 +10,6 @@ import scala.collection.{ mutable, immutable }
import PartialFunction._
import collection.mutable
import util.common.alwaysZero
-import typer.Applications
object Definitions {
@@ -846,6 +845,9 @@ class Definitions {
TupleType(elems.size).appliedTo(elems)
}
+ def isProductSubType(tp: Type)(implicit ctx: Context) =
+ tp.derivesFrom(ProductType.symbol)
+
/** Is `tp` (an alias) of either a scala.FunctionN or a scala.ImplicitFunctionN? */
def isFunctionType(tp: Type)(implicit ctx: Context) = {
val arity = functionArity(tp)
diff --git a/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala b/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala
index e4d2d446f..63c2817a6 100644
--- a/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala
+++ b/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala
@@ -9,7 +9,8 @@ package core
import java.io.IOException
import scala.compat.Platform.currentTime
-import dotty.tools.io.{ ClassPath, AbstractFile }
+import dotty.tools.io.{ ClassPath, ClassRepresentation, AbstractFile }
+import classpath._
import Contexts._, Symbols._, Flags._, SymDenotations._, Types._, Scopes._, util.Positions._, Names._
import StdNames._, NameOps._
import Decorators.{PreNamedString, StringInterpolators}
@@ -60,8 +61,7 @@ class SymbolLoaders {
/** Enter package with given `name` into scope of `owner`
* and give them `completer` as type.
*/
- def enterPackage(owner: Symbol, pkg: ClassPath)(implicit ctx: Context): Symbol = {
- val pname = pkg.name.toTermName
+ def enterPackage(owner: Symbol, pname: TermName, completer: (TermSymbol, ClassSymbol) => PackageLoader)(implicit ctx: Context): Symbol = {
val preExisting = owner.info.decls lookup pname
if (preExisting != NoSymbol) {
// Some jars (often, obfuscated ones) include a package and
@@ -84,7 +84,7 @@ class SymbolLoaders {
}
}
ctx.newModuleSymbol(owner, pname, PackageCreationFlags, PackageCreationFlags,
- (module, modcls) => new PackageLoader(module, pkg)).entered
+ completer).entered
}
/** Enter class and module with given `name` into scope of `owner`
@@ -126,7 +126,7 @@ class SymbolLoaders {
/** Initialize toplevel class and module symbols in `owner` from class path representation `classRep`
*/
- def initializeFromClassPath(owner: Symbol, classRep: ClassPath#ClassRep)(implicit ctx: Context): Unit = {
+ def initializeFromClassPath(owner: Symbol, classRep: ClassRepresentation)(implicit ctx: Context): Unit = {
((classRep.binary, classRep.source): @unchecked) match {
case (Some(bin), Some(src)) if needCompile(bin, src) && !binaryOnly(owner, classRep.name) =>
if (ctx.settings.verbose.value) ctx.inform("[symloader] picked up newer source file for " + src.path)
@@ -144,10 +144,10 @@ class SymbolLoaders {
/** Load contents of a package
*/
- class PackageLoader(_sourceModule: TermSymbol, classpath: ClassPath)
+ class PackageLoader(_sourceModule: TermSymbol, classPath: ClassPath)
extends SymbolLoader {
override def sourceModule(implicit ctx: Context) = _sourceModule
- def description = "package loader " + classpath.name
+ def description(implicit ctx: Context) = "package loader " + sourceModule.fullName
private var enterFlatClasses: Option[Context => Unit] = None
@@ -188,23 +188,25 @@ class SymbolLoaders {
def isFlatName(name: SimpleTermName) = name.lastIndexOf('$', name.length - 2) >= 0
- def isFlatName(classRep: ClassPath#ClassRep) = {
+ def isFlatName(classRep: ClassRepresentation) = {
val idx = classRep.name.indexOf('$')
idx >= 0 && idx < classRep.name.length - 1
}
- def maybeModuleClass(classRep: ClassPath#ClassRep) = classRep.name.last == '$'
+ def maybeModuleClass(classRep: ClassRepresentation) = classRep.name.last == '$'
- private def enterClasses(root: SymDenotation, flat: Boolean)(implicit ctx: Context) = {
- def isAbsent(classRep: ClassPath#ClassRep) =
+ private def enterClasses(root: SymDenotation, packageName: String, flat: Boolean)(implicit ctx: Context) = {
+ def isAbsent(classRep: ClassRepresentation) =
!root.unforcedDecls.lookup(classRep.name.toTypeName).exists
if (!root.isRoot) {
- for (classRep <- classpath.classes)
+ val classReps = classPath.classes(packageName)
+
+ for (classRep <- classReps)
if (!maybeModuleClass(classRep) && isFlatName(classRep) == flat &&
(!flat || isAbsent(classRep))) // on 2nd enter of flat names, check that the name has not been entered before
initializeFromClassPath(root.symbol, classRep)
- for (classRep <- classpath.classes)
+ for (classRep <- classReps)
if (maybeModuleClass(classRep) && isFlatName(classRep) == flat &&
isAbsent(classRep))
initializeFromClassPath(root.symbol, classRep)
@@ -217,14 +219,24 @@ class SymbolLoaders {
root.info = ClassInfo(pre, root.symbol.asClass, Nil, currentDecls, pre select sourceModule)
if (!sourceModule.isCompleted)
sourceModule.completer.complete(sourceModule)
+
+ val packageName = if (root.isEffectiveRoot) "" else root.fullName.toString
+
enterFlatClasses = Some { ctx =>
enterFlatClasses = None
- enterClasses(root, flat = true)(ctx)
+ enterClasses(root, packageName, flat = true)(ctx)
}
- enterClasses(root, flat = false)
+ enterClasses(root, packageName, flat = false)
if (!root.isEmptyPackage)
- for (pkg <- classpath.packages)
- enterPackage(root.symbol, pkg)
+ for (pkg <- classPath.packages(packageName)) {
+ val fullName = pkg.name
+ val name =
+ if (packageName.isEmpty) fullName
+ else fullName.substring(packageName.length + 1)
+
+ enterPackage(root.symbol, name.toTermName,
+ (module, modcls) => new PackageLoader(module, classPath))
+ }
}
}
}
@@ -242,7 +254,7 @@ abstract class SymbolLoader extends LazyType {
/** Description of the resource (ClassPath, AbstractFile)
* being processed by this loader
*/
- def description: String
+ def description(implicit ctx: Context): String
override def complete(root: SymDenotation)(implicit ctx: Context): Unit = {
def signalError(ex: Exception): Unit = {
@@ -283,7 +295,7 @@ class ClassfileLoader(val classfile: AbstractFile) extends SymbolLoader {
override def sourceFileOrNull: AbstractFile = classfile
- def description = "class file " + classfile.toString
+ def description(implicit ctx: Context) = "class file " + classfile.toString
def rootDenots(rootDenot: ClassDenotation)(implicit ctx: Context): (ClassDenotation, ClassDenotation) = {
val linkedDenot = rootDenot.scalacLinkedClass.denot match {
@@ -318,7 +330,7 @@ class ClassfileLoader(val classfile: AbstractFile) extends SymbolLoader {
}
class SourcefileLoader(val srcfile: AbstractFile) extends SymbolLoader {
- def description = "source file " + srcfile.toString
+ def description(implicit ctx: Context) = "source file " + srcfile.toString
override def sourceFileOrNull = srcfile
def doComplete(root: SymDenotation)(implicit ctx: Context): Unit = unsupported("doComplete")
}
diff --git a/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala
index 27afa4d09..9415c047f 100644
--- a/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala
+++ b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala
@@ -7,7 +7,7 @@ import Contexts._, Symbols._, Types._, Names._, StdNames._, NameOps._, Scopes._,
import SymDenotations._, unpickleScala2.Scala2Unpickler._, Constants._, Annotations._, util.Positions._
import NameKinds.{ModuleClassName, DefaultGetterName}
import ast.tpd._
-import java.io.{ File, IOException }
+import java.io.{ ByteArrayInputStream, DataInputStream, File, IOException }
import java.lang.Integer.toHexString
import scala.collection.{ mutable, immutable }
import scala.collection.mutable.{ ListBuffer, ArrayBuffer }
@@ -194,13 +194,21 @@ class ClassfileParser(
val name = pool.getName(in.nextChar)
val isConstructor = name eq nme.CONSTRUCTOR
- /** Strip leading outer param from constructor.
- * Todo: Also strip trailing access tag for private inner constructors?
+ /** Strip leading outer param from constructor and trailing access tag for
+ * private inner constructors.
*/
- def stripOuterParamFromConstructor() = innerClasses.get(currentClassName) match {
+ def normalizeConstructorParams() = innerClasses.get(currentClassName) match {
case Some(entry) if !isStatic(entry.jflags) =>
val mt @ MethodTpe(paramNames, paramTypes, resultType) = denot.info
- denot.info = mt.derivedLambdaType(paramNames.tail, paramTypes.tail, resultType)
+ var normalizedParamNames = paramNames.tail
+ var normalizedParamTypes = paramTypes.tail
+ if ((jflags & JAVA_ACC_SYNTHETIC) != 0) {
+ // SI-7455 strip trailing dummy argument ("access constructor tag") from synthetic constructors which
+ // are added when an inner class needs to access a private constructor.
+ normalizedParamNames = paramNames.dropRight(1)
+ normalizedParamTypes = paramTypes.dropRight(1)
+ }
+ denot.info = mt.derivedLambdaType(normalizedParamNames, normalizedParamTypes, resultType)
case _ =>
}
@@ -216,7 +224,7 @@ class ClassfileParser(
denot.info = pool.getType(in.nextChar)
if (isEnum) denot.info = ConstantType(Constant(sym))
- if (isConstructor) stripOuterParamFromConstructor()
+ if (isConstructor) normalizeConstructorParams()
setPrivateWithin(denot, jflags)
denot.info = translateTempPoly(parseAttributes(sym, denot.info))
if (isConstructor) normalizeConstructorInfo()
@@ -227,8 +235,12 @@ class ClassfileParser(
// seal java enums
if (isEnum) {
val enumClass = sym.owner.linkedClass
- if (!(enumClass is Flags.Sealed)) enumClass.setFlag(Flags.AbstractSealed)
- enumClass.addAnnotation(Annotation.makeChild(sym))
+ if (!enumClass.exists)
+ ctx.warning(s"no linked class for java enum $sym in ${sym.owner}. A referencing class file might be missing an InnerClasses entry.")
+ else {
+ if (!(enumClass is Flags.Sealed)) enumClass.setFlag(Flags.AbstractSealed)
+ enumClass.addAnnotation(Annotation.makeChild(sym))
+ }
}
} finally {
in.bp = oldbp
@@ -665,7 +677,7 @@ class ClassfileParser(
for (entry <- innerClasses.values) {
// create a new class member for immediate inner classes
if (entry.outerName == currentClassName) {
- val file = ctx.platform.classPath.findBinaryFile(entry.externalName.toString) getOrElse {
+ val file = ctx.platform.classPath.findClassFile(entry.externalName.toString) getOrElse {
throw new AssertionError(entry.externalName)
}
enterClassAndModule(entry, file, entry.jflags)
@@ -923,12 +935,16 @@ class ClassfileParser(
case null =>
val start = starts(index)
if (in.buf(start).toInt != CONSTANT_UTF8) errorBadTag(start)
- val name = termName(in.buf, start + 3, in.getChar(start + 1))
+ val len = in.getChar(start + 1).toInt
+ val name = termName(fromMUTF8(in.buf, start + 1, len + 2))
values(index) = name
name
}
}
+ private def fromMUTF8(bytes: Array[Byte], offset: Int, len: Int): String =
+ new DataInputStream(new ByteArrayInputStream(bytes, offset, len)).readUTF
+
/** Return the name found at given index in the constant pool, with '/' replaced by '.'. */
def getExternalName(index: Int): SimpleTermName = {
if (index <= 0 || len <= index)