diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/dotty/tools/dotc/Compiler.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/ast/Desugar.scala | 5 | ||||
-rw-r--r-- | src/dotty/tools/dotc/ast/Trees.scala | 64 | ||||
-rw-r--r-- | src/dotty/tools/dotc/ast/TypedTrees.scala | 4 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Denotations.scala | 6 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Periods.scala | 6 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/SymDenotations.scala | 18 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Symbols.scala | 4 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Types.scala | 4 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/transform/Erasure.scala | 6 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Applications.scala | 10 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Namer.scala | 74 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Typer.scala | 13 |
13 files changed, 145 insertions, 71 deletions
diff --git a/src/dotty/tools/dotc/Compiler.scala b/src/dotty/tools/dotc/Compiler.scala index e094cc06c..6f5e162ee 100644 --- a/src/dotty/tools/dotc/Compiler.scala +++ b/src/dotty/tools/dotc/Compiler.scala @@ -6,6 +6,7 @@ import Contexts._ import Periods._ import Symbols._ import typer.{FrontEnd, Typer} +import reporting.ConsoleReporter class Compiler { @@ -17,6 +18,7 @@ class Compiler { .withPeriod(Period(ctx.runId + 1, FirstPhaseId)) .withOwner(defn.RootClass) .withTyper(new Typer) + .withTyperState(new MutableTyperState(ctx.typerState, new ConsoleReporter()(ctx))) } def newRun(implicit ctx: Context): Run = diff --git a/src/dotty/tools/dotc/ast/Desugar.scala b/src/dotty/tools/dotc/ast/Desugar.scala index 07bf2cd9c..0e1de4b1b 100644 --- a/src/dotty/tools/dotc/ast/Desugar.scala +++ b/src/dotty/tools/dotc/ast/Desugar.scala @@ -8,6 +8,7 @@ import SymDenotations._, Symbols._, StdNames._, Annotations._, Trees._ import Decorators._ import language.higherKinds import collection.mutable.ListBuffer +import typer.ErrorReporting.InfoString import typer.Mode object desugar { @@ -228,11 +229,11 @@ object desugar { val ModuleDef(mods, name, tmpl @ Template(constr, parents, self, body)) = mdef val clsName = name.moduleClassName val clsRef = Ident(clsName) - val modul = ValDef(mods | ModuleCreationFlags, name, clsRef, New(clsRef, Nil)) + val modul = ValDef(mods | ModuleCreationFlags, name, clsRef, New(clsRef, Nil)) withPos mdef.pos val clsSelf = cpy.ValDef(self, self.mods, self.name, SingletonTypeTree(Ident(name)), self.rhs) val clsTmpl = cpy.Template(tmpl, constr, parents, clsSelf, body) val cls = TypeDef(mods.toTypeFlags & AccessFlags | ModuleClassCreationFlags, clsName, clsTmpl) - Thicket(cls, valDef(modul)) + Thicket(valDef(modul), cls) } def memberDef(tree: Tree)(implicit ctx: Context): Tree = tree match { diff --git a/src/dotty/tools/dotc/ast/Trees.scala b/src/dotty/tools/dotc/ast/Trees.scala index 4f467b76f..9eeb28da4 100644 --- a/src/dotty/tools/dotc/ast/Trees.scala +++ b/src/dotty/tools/dotc/ast/Trees.scala @@ -662,7 +662,7 @@ object Trees { extends Tree[T] with WithoutType[T] { type ThisTree[-T >: Untyped] = Thicket[T] override def isEmpty: Boolean = trees.isEmpty - override def toList: List[Tree[T]] = trees + override def toList: List[Tree[T]] = flatten(trees) override def toString = if (isEmpty) "EmptyTree" else "Thicket(" + trees.mkString(", ") + ")" } @@ -686,8 +686,34 @@ object Trees { def forwardTo: Tree[T] = shared } - implicit class ListOfTreeDecorator[T <: untpd.Tree](val xs: List[T]) extends AnyVal { - def tpes: List[Type] = xs map (_.tpe) + def flatten[T >: Untyped](trees: List[Tree[T]]): List[Tree[T]] = { + var buf: ListBuffer[Tree[T]] = null + def add(tree: Tree[T]) = { + assert(!tree.isInstanceOf[Thicket[_]]) + buf += tree + } + var xs = trees + while (xs.nonEmpty) { + xs.head match { + case Thicket(elems) => + if (buf == null) { + buf = new ListBuffer + var ys = trees + while (ys ne xs) { + buf += ys.head + ys = ys.tail + } + } + for (elem <- elems) { + assert(!elem.isInstanceOf[Thicket[_]]) + buf += elem + } + case tree => + if (buf != null) buf += tree + } + xs = xs.tail + } + if (buf != null) buf.toList else trees } // ----- Generic Tree Instances, inherited from `tpt` and `untpd`. @@ -767,37 +793,7 @@ object Trees { def Thicket(x1: Tree, x2: Tree, x3: Tree): Thicket = Thicket(x1 :: x2 :: x3 :: Nil) def flatTree(xs: List[Tree]): Tree = flatten(xs) match { case x :: Nil => x - case _ => Thicket(xs) - } - - def flatten(trees: List[Tree]): List[Tree] = { - var buf: ListBuffer[Tree] = null - def add(tree: Tree) = { - assert(!tree.isInstanceOf[Thicket]) - buf += tree - } - var xs = trees - while (xs.nonEmpty) { - xs.head match { - case Thicket(elems) => - if (buf == null) { - buf = new ListBuffer - var ys = trees - while (ys ne xs) { - buf += ys.head - ys = ys.tail - } - } - for (elem <- elems) { - assert(!elem.isInstanceOf[Thicket]) - buf += elem - } - case tree => - if (buf != null) buf += tree - } - xs = xs.tail - } - if (buf != null) buf.toList else trees + case ys => Thicket(ys) } // ----- Position handling ----------------------------------------- diff --git a/src/dotty/tools/dotc/ast/TypedTrees.scala b/src/dotty/tools/dotc/ast/TypedTrees.scala index 3530accfc..9942728b3 100644 --- a/src/dotty/tools/dotc/ast/TypedTrees.scala +++ b/src/dotty/tools/dotc/ast/TypedTrees.scala @@ -393,6 +393,10 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { new TreeMapper(ownerMap = (sym => if (sym == from) to else sym)).apply(tree) } + implicit class ListOfTreeDecorator(val xs: List[tpd.Tree]) extends AnyVal { + def tpes: List[Type] = xs map (_.tpe) + } + class TreeMapper(val typeMap: TypeMap = IdentityTypeMap, val ownerMap: Symbol => Symbol = identity)(implicit ctx: Context) extends TreeTransformer { override def transform(tree: tpd.Tree)(implicit ctx: Context): tpd.Tree = super.transform { tree.withType(typeMap(tree.tpe)) match { diff --git a/src/dotty/tools/dotc/core/Denotations.scala b/src/dotty/tools/dotc/core/Denotations.scala index e551c8af2..4566cfdb8 100644 --- a/src/dotty/tools/dotc/core/Denotations.scala +++ b/src/dotty/tools/dotc/core/Denotations.scala @@ -456,7 +456,9 @@ object Denotations { val valid = myValidFor def stillValid(denot: SymDenotation): Boolean = if (!denot.exists || (denot.flags is PackageClass)) true - else if (denot.owner is PackageClass) denot.owner.decls.lookup(denot.name) eq symbol + else if (denot.owner is PackageClass) + (denot.owner.decls.lookup(denot.name) eq denot.symbol) || + (denot is ModuleClass) && stillValid(denot.sourceModule) // !!! DEBUG - we should check why module classes are not entered else stillValid(denot.owner) def bringForward(): SingleDenotation = this match { case denot: SymDenotation if stillValid(denot) => @@ -467,7 +469,7 @@ object Denotations { } while (d ne denot) initial.copyIfParentInvalid case _ => - throw new Error(s"stale symbol; ${symbol.showLocated}, defined in run ${valid.runId} is referred to in run ${currentPeriod.runId}") + throw new Error(s"stale symbol; $this, defined in run ${valid.runId} is referred to in run ${currentPeriod.runId}") } if (valid.runId != currentPeriod.runId) bringForward.current else { diff --git a/src/dotty/tools/dotc/core/Periods.scala b/src/dotty/tools/dotc/core/Periods.scala index 55a485201..8a1b65f2c 100644 --- a/src/dotty/tools/dotc/core/Periods.scala +++ b/src/dotty/tools/dotc/core/Periods.scala @@ -56,13 +56,13 @@ object Periods { class Period(val code: Int) extends AnyVal { /** The run identifier of this period. */ - def runId: Int = code >>> (PhaseWidth * 2) + def runId: RunId = code >>> (PhaseWidth * 2) /** The phase identifier of this single-phase period. */ - def phaseId: Int = (code >>> PhaseWidth) & PhaseMask + def phaseId: PhaseId = (code >>> PhaseWidth) & PhaseMask /** The last phase of this period */ - def lastPhaseId: Int = + def lastPhaseId: PhaseId = (code >>> PhaseWidth) & PhaseMask /** The first phase of this period */ diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala index d2b2a6fe4..910fec909 100644 --- a/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/src/dotty/tools/dotc/core/SymDenotations.scala @@ -437,11 +437,15 @@ object SymDenotations { * the completers. */ /** The class implementing this module, NoSymbol if not applicable. */ - final def moduleClass: Symbol = myInfo match { - case info: TypeRefBySym if this is ModuleVal => info.fixedSym - case info: ModuleCompleter => info.mclass - case _ => NoSymbol - } + final def moduleClass: Symbol = + if (this is ModuleVal) + myInfo match { + case info: TypeRefBySym => info.fixedSym + case ExprType(info: TypeRefBySym) => info.fixedSym // needed after uncurry, when module terms might be accessor defs + case info: ModuleCompleter => info.mclass + case _ => NoSymbol + } + else NoSymbol /** The module implemented by this module class, NoSymbol if not applicable. */ final def sourceModule: Symbol = myInfo match { @@ -841,6 +845,10 @@ object SymDenotations { case scope: MutableScope => scope case _ => decls.asInstanceOf[MutableScope] } + if (this is PackageClass) { // replace existing symbols + val entry = mscope.lookupEntry(sym.name) + if (entry != null) mscope.unlink(entry) + } mscope.enter(sym) if (myMemberFingerPrint != FingerPrint.unknown) diff --git a/src/dotty/tools/dotc/core/Symbols.scala b/src/dotty/tools/dotc/core/Symbols.scala index 1e3fe4e52..3e8b13320 100644 --- a/src/dotty/tools/dotc/core/Symbols.scala +++ b/src/dotty/tools/dotc/core/Symbols.scala @@ -320,6 +320,10 @@ object Symbols { denot } + /** The run-id when this symbol was last defined */ + final def defRunId: RunId = + if (lastDenot == null) NoRunId else lastDenot.validFor.runId + /** Subclass tests and casts */ final def isTerm(implicit ctx: Context): Boolean = denot.isTerm final def isType(implicit ctx: Context): Boolean = denot.isType diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala index 49ad67c49..cf756859f 100644 --- a/src/dotty/tools/dotc/core/Types.scala +++ b/src/dotty/tools/dotc/core/Types.scala @@ -330,6 +330,8 @@ object Types { tp.decls.denotsNamed(name).filterExcluded(excluded).toDenot(NoPrefix) case tp: TypeProxy => tp.underlying.findDecl(name, excluded) + case ErrorType => + ctx.newErrorSymbol(classSymbol orElse defn.RootClass, name) } /** The member of this type with the given name */ @@ -756,6 +758,8 @@ object Types { tp.underlying.appliedTo(args) case AndType(l, r) => l.appliedTo(args) & r + case ErrorType => + this } } diff --git a/src/dotty/tools/dotc/core/transform/Erasure.scala b/src/dotty/tools/dotc/core/transform/Erasure.scala index 5b8a492e1..31679f05e 100644 --- a/src/dotty/tools/dotc/core/transform/Erasure.scala +++ b/src/dotty/tools/dotc/core/transform/Erasure.scala @@ -2,7 +2,7 @@ package dotty.tools.dotc package core package transform -import Symbols._, Types._, Contexts._, Flags._, Names._ +import Symbols._, Types._, Contexts._, Flags._, Names._, StdNames._ object Erasure { @@ -63,6 +63,8 @@ object Erasure { else if (cls == defn.ArrayClass) defn.ObjectClass.typeConstructor :: Nil else removeLaterObjects(classParents mapConserve (erasure(_).asInstanceOf[TypeRef])) tp.derivedClassInfo(erasure(pre), parents, NoType) + case ErrorType => + tp } def eraseArray(tp: RefinedType)(implicit ctx: Context) = { @@ -124,6 +126,8 @@ object Erasure { paramSignature(tp1) case OrType(tp1, tp2) => lubClass(tp1, tp2).name + case ErrorType => + tpnme.WILDCARD } def resultErasure(tp: Type)(implicit ctx: Context) = diff --git a/src/dotty/tools/dotc/typer/Applications.scala b/src/dotty/tools/dotc/typer/Applications.scala index 334e21ccb..439210af4 100644 --- a/src/dotty/tools/dotc/typer/Applications.scala +++ b/src/dotty/tools/dotc/typer/Applications.scala @@ -154,13 +154,13 @@ trait Applications extends Compatibility { self: Typer => /** The arguments re-ordered so that each named argument matches the * same-named formal parameter. */ - val orderedArgs = + lazy val orderedArgs = if (hasNamedArg(args)) reorder(args.asInstanceOf[List[untpd.Tree]]).asInstanceOf[List[Arg]] else args - methType match { + protected def init() = methType match { case methType: MethodType => // apply the result type constraint, unless method type is dependent if (!methType.isDependent) @@ -248,9 +248,9 @@ trait Applications extends Compatibility { self: Typer => def findDefault(cx: Context): Type = { if (cx eq NoContext) NoType else if (cx.scope != cx.outer.scope && - cx.lookup(methRef.name) + cx.denotsNamed(methRef.name) .filterWithPredicate(_.symbol == meth).exists) { - val denot = cx.lookup(getterName).toDenot(NoPrefix) + val denot = cx.denotsNamed(getterName).toDenot(NoPrefix) NamedType(NoPrefix, getterName).withDenot(denot) } else findDefault(cx.outer) } @@ -368,6 +368,7 @@ trait Applications extends Compatibility { self: Typer => def fail(msg: => String) = ok = false def normalizedFun = EmptyTree + init() } /** Subtrait of Application for the cases where arguments are (typed or @@ -403,6 +404,7 @@ trait Applications extends Compatibility { self: Typer => private var typedArgBuf = new mutable.ListBuffer[Tree] private var liftedDefs: mutable.ListBuffer[Tree] = null private var myNormalizedFun: Tree = fun + init() def addArg(arg: Tree, formal: Type): Unit = typedArgBuf += adapt(arg, formal) diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala index 12c812c22..024577b47 100644 --- a/src/dotty/tools/dotc/typer/Namer.scala +++ b/src/dotty/tools/dotc/typer/Namer.scala @@ -12,6 +12,7 @@ import util.Positions._ import util.SourcePosition import collection.mutable import annotation.tailrec +import ErrorReporting._ import language.implicitConversions trait NamerContextOps { this: Context => @@ -24,9 +25,13 @@ trait NamerContextOps { this: Context => sym } - def lookup(name: Name): PreDenotation = - if (isClassDefContext) owner.asClass.membersNamed(name) + def denotsNamed(name: Name): PreDenotation = + if (owner.isClass) owner.asClass.membersNamed(name) else scope.denotsNamed(name) + + def effectiveScope = + if (owner != null && owner.isClass) owner.asClass.decls + else scope } /** This class attaches creates symbols from definitions and imports and gives them @@ -106,25 +111,49 @@ class Namer { typer: Typer => * and store in symOfTree map. */ def createSymbol(tree: Tree)(implicit ctx: Context): Symbol = { + def privateWithinClass(mods: Modifiers) = enclosingClassNamed(mods.privateWithin, mods.pos) - val sym = tree match { + + def record(tree: Tree, sym: Symbol): Symbol = { + symOfTree(tree) = sym + println(s"entered: $sym in ${ctx.owner} and ${ctx.effectiveScope}") + sym + } + + def recordEnter(tree: Tree, sym: Symbol) = { + if (sym.owner is PackageClass) { + val preExisting = sym.owner.decls.lookup(sym.name) + if (preExisting.defRunId == ctx.runId) + ctx.error(s"${sym.showLocated} is compiled twice", tree.pos) + } + record(tree, ctx.enter(sym)) + } + + println(i"creating symbol for $tree") + tree match { case tree: TypeDef if tree.isClassDef => - ctx.enter(ctx.newClassSymbol( + recordEnter(tree, ctx.newClassSymbol( ctx.owner, tree.name, tree.mods.flags, new ClassCompleter(tree), privateWithinClass(tree.mods), tree.pos, ctx.source.file)) + case Thicket((moduleDef: ValDef) :: (modclsDef: TypeDef) :: Nil) => + assert(moduleDef.mods is Module) + val module = ctx.newModuleSymbol( + ctx.owner, moduleDef.name, moduleDef.mods.flags, modclsDef.mods.flags, + (modul, modcls) => new ClassCompleter(modclsDef, modul), + privateWithinClass(moduleDef.mods), modclsDef.pos, ctx.source.file) + recordEnter(modclsDef, module.moduleClass) + recordEnter(moduleDef, module) case tree: MemberDef => - ctx.enter(ctx.newSymbol( + recordEnter(tree, ctx.newSymbol( ctx.owner, tree.name, tree.mods.flags, new Completer(tree), privateWithinClass(tree.mods), tree.pos)) case imp: Import => - ctx.newSymbol( - ctx.owner, nme.IMPORT, Synthetic, new Completer(tree), NoSymbol, tree.pos) + record(imp, ctx.newSymbol( + ctx.owner, nme.IMPORT, Synthetic, new Completer(tree), NoSymbol, tree.pos)) case _ => NoSymbol } - if (sym.exists) symOfTree(tree) = sym - sym } /** All PackageClassInfoTypes come from here. */ @@ -165,6 +194,9 @@ class Namer { typer: Typer => ctx case imp: Import => importContext(createSymbol(imp), imp.selectors) + case mdef: ModuleDef => + createSymbol(expansion(mdef)) + ctx case mdef: MemberDef => expansion(mdef).toList foreach createSymbol ctx @@ -234,12 +266,13 @@ class Namer { typer: Typer => } /** The completer for a symbol defined by a class definition */ - class ClassCompleter(original: TypeDef, override val decls: MutableScope = newScope)(implicit ctx: Context) - extends ClassCompleterWithDecls(decls) { + class ClassCompleter(original: TypeDef, override val sourceModule: Symbol = NoSymbol)(implicit ctx: Context) + extends ClassCompleterWithDecls(newScope) { override def complete(denot: SymDenotation): Unit = { val cls = denot.symbol.asClass def localContext = ctx.fresh.withOwner(cls) - cls.info = classDefSig(original, cls, decls)(localContext) + println(s"completing ${cls.show}, sourceModule = ${sourceModule.show}") + cls.info = classDefSig(original, cls, decls.asInstanceOf[MutableScope])(localContext) } } @@ -248,7 +281,7 @@ class Namer { typer: Typer => typedTree.getOrElseUpdate(tree, typer.typedExpanded(tree, pt)) def typedAheadType(tree: Tree, pt: Type = WildcardType)(implicit ctx: Context): tpd.Tree = - typedAheadImpl(tree, WildcardType)(ctx retractMode Mode.PatternOrType addMode Mode.Type) + typedAheadImpl(tree, pt)(ctx retractMode Mode.PatternOrType addMode Mode.Type) def typedAheadExpr(tree: Tree, pt: Type = WildcardType)(implicit ctx: Context): tpd.Tree = typedAheadImpl(tree, pt)(ctx retractMode Mode.PatternOrType) @@ -342,7 +375,7 @@ class Namer { typer: Typer => else typedAheadExpr(constr).tpe } - val TypeDef(_, _, impl @ Template(_, parents, self, body)) = cdef + val TypeDef(_, _, impl @ Template(constr, parents, self, body)) = cdef val (params, rest) = body span { case td: TypeDef => td.mods is Param @@ -350,9 +383,20 @@ class Namer { typer: Typer => case _ => false } enterSyms(params) + def defaultSelfType = + if (cls is Module) TermRef.withSym(ctx.owner.thisType, cls.sourceModule.asTerm) + else NoType + // pre-set info, so that parent types can refer to type params + cls.info = ClassInfo(cls.owner.thisType, cls, Nil, decls, defaultSelfType) val parentTypes = parents map parentType val parentRefs = ctx.normalizeToRefs(parentTypes, cls, decls) - val optSelfType = if (self.tpt.isEmpty) NoType else typedAheadType(self.tpt).tpe + val optSelfType = + if (self.tpt.isEmpty) defaultSelfType + else { + val t = typedAheadType(self.tpt).tpe + if (!t.isError) t else defaultSelfType + } + enterSym(constr) enterSyms(rest)(inClassContext(cls, self.name)) ClassInfo(cls.owner.thisType, cls, parentRefs, decls, optSelfType) } diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala index b4e1335f8..6922111f4 100644 --- a/src/dotty/tools/dotc/typer/Typer.scala +++ b/src/dotty/tools/dotc/typer/Typer.scala @@ -268,11 +268,11 @@ class Typer extends Namer with Applications with Implicits { } // begin findRef - if (ctx eq NoContext) previous + if (ctx.scope == null) previous else { val outer = ctx.outer - if (ctx.scope ne outer.scope) { - val defDenots = ctx.lookup(name) + if ((ctx.scope ne outer.scope) || (ctx.owner ne outer.owner)) { + val defDenots = ctx.denotsNamed(name) if (defDenots.exists) { val curOwner = ctx.owner val pre = curOwner.thisType @@ -299,6 +299,8 @@ class Typer extends Namer with Applications with Implicits { } // begin typedIdent + def kind = if (name.isTermName) "term" else "type" // !!! DEBUG + println(s"typed ident $kind $name in ${ctx.owner}") if (ctx.mode is Mode.Pattern) { if (name == nme.WILDCARD) return tree.withType(pt) @@ -369,7 +371,7 @@ class Typer extends Namer with Applications with Implicits { case _ => val tpt1 = typedType(tree.tpt) val cls = checkClassTypeWithStablePrefix(tpt1.tpe, tpt1.pos) - checkInstantiatable(cls, tpt1.pos) + // todo in a later phase: checkInstantiatable(cls, tpt1.pos) cpy.New(tree, tpt1).withType(tpt1.tpe) } @@ -594,7 +596,7 @@ class Typer extends Namer with Applications with Implicits { assert(isFullyDefined(pt)) (EmptyTree, pt) case original: DefDef => - val meth = ctx.lookup(original.name).first + val meth = symbolOfTree(original) assert(meth.exists, meth) (EmptyTree, meth.info.resultType) case original => @@ -815,6 +817,7 @@ class Typer extends Namer with Applications with Implicits { case tree: untpd.Import => typedImport(tree, sym) case tree: untpd.PackageDef => typedPackageDef(tree) case tree: untpd.Annotated => typedAnnotated(tree, pt) + case tree: untpd.TypedSplice => tree.tree case untpd.EmptyTree => tpd.EmptyTree case _ => typed(desugar(tree), pt) } |