From 0bba0aaf5478bcab197f4d88e398955ed2581580 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Fri, 22 Feb 2013 19:17:04 +0100 Subject: [PATCH 01/22] Populate the lastDenot cache. --- src/dotty/tools/dotc/core/Symbols.scala | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/dotty/tools/dotc/core/Symbols.scala b/src/dotty/tools/dotc/core/Symbols.scala index 68579f15f419..3615a2cca2eb 100644 --- a/src/dotty/tools/dotc/core/Symbols.scala +++ b/src/dotty/tools/dotc/core/Symbols.scala @@ -187,7 +187,10 @@ object Symbols { /** The current denotation of this symbol */ final def denot(implicit ctx: Context): SymDenotation = { var denot = lastDenot - if (!(denot.validFor contains ctx.period)) denot = denot.current.asInstanceOf[SymDenotation] + if (!(denot.validFor contains ctx.period)) { + denot = denot.current.asInstanceOf[SymDenotation] + lastDenot = denot + } denot } From aec56f28e6df9fa05bfab9e019dbe2be3b06150d Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Fri, 22 Feb 2013 19:34:16 +0100 Subject: [PATCH 02/22] Make leaf tree nodes final. Notable omissions are ValDef and DefDef, which are subclassed by the empty variety. Final classes are easier for the reader to reason about and enable additional static analysis by the compiler. As an example of the latter, scala> trait T defined trait T scala> Tuple1(0) match { case _: T => true; case _ => false } res0: Boolean = false scala> final case class T1[A](a: A) defined class T1 scala> T1(0) match { case _: T => true; case _ => false } :11: error: scrutinee is incompatible with pattern type; found : T required: T1[Int] T1(0) match { case _: T => true; case _ => false } --- src/dotty/tools/dotc/core/Trees.scala | 82 +++++++++++++-------------- src/dotty/tools/dotc/core/Types.scala | 1 + 2 files changed, 42 insertions(+), 41 deletions(-) diff --git a/src/dotty/tools/dotc/core/Trees.scala b/src/dotty/tools/dotc/core/Trees.scala index 6215cfc69ff8..9a842c71faad 100644 --- a/src/dotty/tools/dotc/core/Trees.scala +++ b/src/dotty/tools/dotc/core/Trees.scala @@ -177,7 +177,7 @@ object Trees { // ----------- Tree case classes ------------------------------------ /** name */ - case class Ident[T](name: Name)(implicit cpos: Position) + final case class Ident[T](name: Name)(implicit cpos: Position) extends RefTree[T] { type ThisTree[T] = Ident[T] val pos = cpos @@ -185,21 +185,21 @@ object Trees { } /** qualifier.name */ - case class Select[T](qualifier: Tree[T], name: Name)(implicit cpos: Position) + final case class Select[T](qualifier: Tree[T], name: Name)(implicit cpos: Position) extends RefTree[T] { type ThisTree[T] = Select[T] val pos = cpos union qualifier.pos } /** qual.this */ - case class This[T](qual: TypeName)(implicit cpos: Position) + final case class This[T](qual: TypeName)(implicit cpos: Position) extends SymTree[T] with TermTree[T] { type ThisTree[T] = This[T] val pos = cpos } /** C.super[mix], where qual = C.this */ - case class Super[T](qual: Tree[T], mix: TypeName)(implicit cpos: Position) + final case class Super[T](qual: Tree[T], mix: TypeName)(implicit cpos: Position) extends ProxyTree[T] with TermTree[T] { type ThisTree[T] = Super[T] val pos = cpos union qual.pos @@ -214,42 +214,42 @@ object Trees { } /** fun(args) */ - case class Apply[T](fun: Tree[T], args: List[Tree[T]])(implicit cpos: Position) + final case class Apply[T](fun: Tree[T], args: List[Tree[T]])(implicit cpos: Position) extends GenericApply[T] { type ThisTree[T] = Apply[T] val pos = unionPos(cpos union fun.pos, args) } /** fun[args] */ - case class TypeApply[T](fun: Tree[T], args: List[Tree[T]])(implicit cpos: Position) + final case class TypeApply[T](fun: Tree[T], args: List[Tree[T]])(implicit cpos: Position) extends GenericApply[T] { type ThisTree[T] = TypeApply[T] val pos = unionPos(cpos union fun.pos, args) } /** const */ - case class Literal[T](const: Constant)(implicit cpos: Position) + final case class Literal[T](const: Constant)(implicit cpos: Position) extends TermTree[T] { type ThisTree[T] = Literal[T] val pos = cpos } /** new tpt, but no constructor call */ - case class New[T](tpt: Tree[T])(implicit cpos: Position) + final case class New[T](tpt: Tree[T])(implicit cpos: Position) extends TermTree[T] { type ThisTree[T] = New[T] val pos = cpos union tpt.pos } /** (left, right) */ - case class Pair[T](left: Tree[T], right: Tree[T])(implicit cpos: Position) + final case class Pair[T](left: Tree[T], right: Tree[T])(implicit cpos: Position) extends TermTree[T] { type ThisTree[T] = Pair[T] val pos = cpos union left.pos union right.pos } /** expr : tpt */ - case class Typed[T](expr: Tree[T], tpt: Tree[T])(implicit cpos: Position) + final case class Typed[T](expr: Tree[T], tpt: Tree[T])(implicit cpos: Position) extends ProxyTree[T] with TermTree[T] { type ThisTree[T] = Typed[T] val pos = cpos union expr.pos union tpt.pos @@ -257,42 +257,42 @@ object Trees { } /** name = arg, in a parameter list */ - case class NamedArg[T](name: Name, arg: Tree[T])(implicit cpos: Position) + final case class NamedArg[T](name: Name, arg: Tree[T])(implicit cpos: Position) extends Tree[T] { type ThisTree[T] = NamedArg[T] val pos = cpos union arg.pos } /** name = arg, outside a parameter list */ - case class Assign[T](lhs: Tree[T], rhs: Tree[T])(implicit cpos: Position) + final case class Assign[T](lhs: Tree[T], rhs: Tree[T])(implicit cpos: Position) extends TermTree[T] { type ThisTree[T] = Assign[T] val pos = cpos union lhs.pos union rhs.pos } /** { stats; expr } */ - case class Block[T](stats: List[Tree[T]], expr: Tree[T])(implicit cpos: Position) + final case class Block[T](stats: List[Tree[T]], expr: Tree[T])(implicit cpos: Position) extends TermTree[T] { type ThisTree[T] = Block[T] val pos = unionPos(cpos union expr.pos, stats) } /** if cond then thenp else elsep */ - case class If[T](cond: Tree[T], thenp: Tree[T], elsep: Tree[T])(implicit cpos: Position) + final case class If[T](cond: Tree[T], thenp: Tree[T], elsep: Tree[T])(implicit cpos: Position) extends TermTree[T] { type ThisTree[T] = If[T] val pos = cpos union cond.pos union thenp.pos union elsep.pos } /** selector match { cases } */ - case class Match[T](selector: Tree[T], cases: List[CaseDef[T]])(implicit cpos: Position) + final case class Match[T](selector: Tree[T], cases: List[CaseDef[T]])(implicit cpos: Position) extends TermTree[T] { type ThisTree[T] = Match[T] val pos = unionPos(cpos union selector.pos, cases) } /** case pat if guard => body */ - case class CaseDef[T](pat: Tree[T], guard: Tree[T], body: Tree[T])(implicit cpos: Position) + final case class CaseDef[T](pat: Tree[T], guard: Tree[T], body: Tree[T])(implicit cpos: Position) extends Tree[T] { type ThisTree[T] = CaseDef[T] val pos = cpos union pat.pos union guard.pos union body.pos @@ -303,70 +303,70 @@ object Trees { * After program transformations this is not necessarily the enclosing method, because * closures can intervene. */ - case class Return[T](expr: Tree[T], from: Ident[T])(implicit cpos: Position) + final case class Return[T](expr: Tree[T], from: Ident[T])(implicit cpos: Position) extends TermTree[T] { type ThisTree[T] = Return[T] val pos = cpos union expr.pos // from is synthetic, does not influence pos } /** try block catch { catches } */ - case class Try[T](block: Tree[T], catches: List[CaseDef[T]], finalizer: Tree[T])(implicit cpos: Position) + final case class Try[T](block: Tree[T], catches: List[CaseDef[T]], finalizer: Tree[T])(implicit cpos: Position) extends TermTree[T] { type ThisTree[T] = Try[T] val pos = unionPos(cpos union block.pos union finalizer.pos, catches) } /** throw expr */ - case class Throw[T](expr: Tree[T])(implicit cpos: Position) + final case class Throw[T](expr: Tree[T])(implicit cpos: Position) extends TermTree[T] { type ThisTree[T] = Throw[T] val pos = cpos union expr.pos } /** Array[elemtpt](elems) */ - case class SeqLiteral[T](elemtpt: Tree[T], elems: List[Tree[T]])(implicit cpos: Position) + final case class SeqLiteral[T](elemtpt: Tree[T], elems: List[Tree[T]])(implicit cpos: Position) extends Tree[T] { type ThisTree[T] = SeqLiteral[T] val pos = unionPos(cpos union elemtpt.pos, elems) } /** A type tree that represents an existing or inferred type */ - case class TypeTree[T](original: Tree[T] = EmptyTree[T])(implicit cpos: Position) + final case class TypeTree[T](original: Tree[T] = EmptyTree[T])(implicit cpos: Position) extends SymTree[T] with TypTree[T] { type ThisTree[T] = TypeTree[T] val pos = cpos union original.pos } /** ref.type */ - case class SingletonTypeTree[T](ref: Tree[T])(implicit cpos: Position) + final case class SingletonTypeTree[T](ref: Tree[T])(implicit cpos: Position) extends SymTree[T] with TypTree[T] { type ThisTree[T] = SingletonTypeTree[T] val pos = cpos union ref.pos } /** qualifier # name */ - case class SelectFromTypeTree[T](qualifier: Tree[T], name: TypeName)(implicit cpos: Position) + final case class SelectFromTypeTree[T](qualifier: Tree[T], name: TypeName)(implicit cpos: Position) extends RefTree[T] with TypTree[T] { type ThisTree[T] = SelectFromTypeTree[T] val pos = cpos union qualifier.pos } /** left & right */ - case class AndTypeTree[T](left: Tree[T], right: Tree[T])(implicit cpos: Position) + final case class AndTypeTree[T](left: Tree[T], right: Tree[T])(implicit cpos: Position) extends TypTree[T] { type ThisTree[T] = AndTypeTree[T] val pos = cpos union left.pos union right.pos } /** left | right */ - case class OrTypeTree[T](left: Tree[T], right: Tree[T])(implicit cpos: Position) + final case class OrTypeTree[T](left: Tree[T], right: Tree[T])(implicit cpos: Position) extends TypTree[T] { type ThisTree[T] = OrTypeTree[T] val pos = cpos union left.pos union right.pos } /** tpt { refinements } */ - case class RefineTypeTree[T](tpt: Tree[T], refinements: List[DefTree[T]])(implicit cpos: Position) + final case class RefineTypeTree[T](tpt: Tree[T], refinements: List[DefTree[T]])(implicit cpos: Position) extends ProxyTree[T] with TypTree[T] { type ThisTree[T] = RefineTypeTree[T] val pos = unionPos(cpos union tpt.pos, refinements) @@ -374,7 +374,7 @@ object Trees { } /** tpt[args] */ - case class AppliedTypeTree[T](tpt: Tree[T], args: List[Tree[T]])(implicit cpos: Position) + final case class AppliedTypeTree[T](tpt: Tree[T], args: List[Tree[T]])(implicit cpos: Position) extends ProxyTree[T] with TypTree[T] { type ThisTree[T] = AppliedTypeTree[T] val pos = unionPos(cpos union tpt.pos, args) @@ -382,28 +382,28 @@ object Trees { } /** >: lo <: hi */ - case class TypeBoundsTree[T](lo: Tree[T], hi: Tree[T])(implicit cpos: Position) + final case class TypeBoundsTree[T](lo: Tree[T], hi: Tree[T])(implicit cpos: Position) extends Tree[T] { type ThisTree[T] = TypeBoundsTree[T] val pos = cpos union lo.pos union hi.pos } /** name @ body */ - case class Bind[T](name: Name, body: Tree[T])(implicit cpos: Position) + final case class Bind[T](name: Name, body: Tree[T])(implicit cpos: Position) extends DefTree[T] with PatternTree[T] { type ThisTree[T] = Bind[T] val pos = cpos union body.pos } /** tree_1 | ... | tree_n */ - case class Alternative[T](trees: List[Tree[T]])(implicit cpos: Position) + final case class Alternative[T](trees: List[Tree[T]])(implicit cpos: Position) extends Tree[T] with PatternTree[T] { type ThisTree[T] = Alternative[T] val pos = unionPos(cpos, trees) } /** fun(args) in a pattern, if fun is an extractor */ - case class UnApply[T](fun: Tree[T], args: List[Tree[T]])(implicit cpos: Position) + final case class UnApply[T](fun: Tree[T], args: List[Tree[T]])(implicit cpos: Position) extends Tree[T] with PatternTree[T] { type ThisTree[T] = UnApply[T] val pos = unionPos(cpos union fun.pos, args) @@ -423,7 +423,7 @@ object Trees { val pos = (unionPos(cpos union tpt.pos union rhs.pos, tparams) /: vparamss)(unionPos) } - class ImplicitDefDef[T](mods: Modifiers[T], name: Name, tparams: List[TypeDef[T]], vparamss: List[List[ValDef[T]]], tpt: Tree[T], rhs: Tree[T])(implicit pos: Position) extends DefDef[T](mods, name, tparams, vparamss, tpt, rhs) { + final class ImplicitDefDef[T](mods: Modifiers[T], name: Name, tparams: List[TypeDef[T]], vparamss: List[List[ValDef[T]]], tpt: Tree[T], rhs: Tree[T])(implicit pos: Position) extends DefDef[T](mods, name, tparams, vparamss, tpt, rhs) { override def copy[T](mods: Modifiers[T], name: Name, tparams: List[TypeDef[T]], vparamss: List[List[ValDef[T]]], tpt: Tree[T], rhs: Tree[T])(implicit pos: Position) = new ImplicitDefDef[T](mods, name, tparams, vparamss, tpt, rhs) } @@ -431,7 +431,7 @@ object Trees { /** mods type name = rhs or * mods type name >: lo <: hi, if rhs = TypeBoundsTree(lo, hi) */ - case class TypeDef[T](mods: Modifiers[T], name: Name, rhs: Tree[T])(implicit cpos: Position) + final case class TypeDef[T](mods: Modifiers[T], name: Name, rhs: Tree[T])(implicit cpos: Position) extends DefTree[T] { type ThisTree[T] = TypeDef[T] val pos = cpos union rhs.pos @@ -445,7 +445,7 @@ object Trees { } /** mods class name[tparams] impl */ - case class ClassDef[T](mods: Modifiers[T], name: TypeName, tparams: List[TypeDef[T]], impl: Template[T])(implicit cpos: Position) + final case class ClassDef[T](mods: Modifiers[T], name: TypeName, tparams: List[TypeDef[T]], impl: Template[T])(implicit cpos: Position) extends DefTree[T] { type ThisTree[T] = ClassDef[T] val pos = unionPos(cpos union impl.pos, tparams) @@ -455,14 +455,14 @@ object Trees { * where a selector is either an untyped `Ident`, `name` or * an untyped `Pair` `name => rename` */ - case class Import[T](expr: Tree[T], selectors: List[UntypedTree])(implicit cpos: Position) + final case class Import[T](expr: Tree[T], selectors: List[UntypedTree])(implicit cpos: Position) extends SymTree[T] { type ThisTree[T] = Import[T] val pos = unionPos(cpos union expr.pos, selectors) } /** package pid { stats } */ - case class PackageDef[T](pid: RefTree[T], stats: List[Tree[T]])(implicit cpos: Position) + final case class PackageDef[T](pid: RefTree[T], stats: List[Tree[T]])(implicit cpos: Position) extends DefTree[T] { type ThisTree[T] = PackageDef[T] val pos = unionPos(cpos union pid.pos, stats) @@ -470,7 +470,7 @@ object Trees { } /** arg @annot */ - case class Annotated[T](annot: Tree[T], arg: Tree[T])(implicit cpos: Position) + final case class Annotated[T](annot: Tree[T], arg: Tree[T])(implicit cpos: Position) extends ProxyTree[T] { type ThisTree[T] = Annotated[T] val pos = cpos union annot.pos union arg.pos @@ -496,7 +496,7 @@ object Trees { def apply[T]: EmptyTree[T] = theEmptyTree.asInstanceOf } - class EmptyValDef[T] extends ValDef[T]( + abstract class EmptyValDef[T] extends ValDef[T]( Modifiers[T](Private), nme.WILDCARD, EmptyTree[T], EmptyTree[T])(NoPosition) with AlwaysEmpty[T] private object theEmptyValDef extends EmptyValDef[Nothing] @@ -509,7 +509,7 @@ object Trees { * polluting containing trees. Accumulators and tranformers * memoize results of shared subtrees */ - case class Shared[T](shared: Tree[T]) extends Tree[T] { + final case class Shared[T](shared: Tree[T]) extends Tree[T] { type ThisTree[T] = Shared[T] val pos = NoPosition override val isTerm = shared.isTerm @@ -524,13 +524,13 @@ object Trees { } /** mods object name impl */ - case class ModuleDef(mods: Modifiers[Nothing], name: TermName, impl: Template[Nothing])(implicit cpos: Position) + final case class ModuleDef(mods: Modifiers[Nothing], name: TermName, impl: Template[Nothing])(implicit cpos: Position) extends DefTree[Nothing] { val pos = cpos union impl.pos } /** (vparams) => body */ - case class Function(vparams: List[ValDef[Nothing]], body: Tree[Nothing])(implicit cpos: Position) + final case class Function(vparams: List[ValDef[Nothing]], body: Tree[Nothing])(implicit cpos: Position) extends TermTree[Nothing] { val pos = unionPos(cpos union body.pos, vparams) } diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala index 60facee3c2a4..d0c821ea66e5 100644 --- a/src/dotty/tools/dotc/core/Types.scala +++ b/src/dotty/tools/dotc/core/Types.scala @@ -18,6 +18,7 @@ import collection.mutable object Types { + /** A hash value indicating that the underlying type is not * cached in uniques. */ From 837771d29e0ad43d8dfbacfa28467302f8d37331 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Sat, 23 Feb 2013 01:05:10 +0100 Subject: [PATCH 03/22] Make Types final or sealed. --- src/dotty/tools/dotc/core/Types.scala | 36 +++++++++++++-------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala index d0c821ea66e5..664f38fc7f7f 100644 --- a/src/dotty/tools/dotc/core/Types.scala +++ b/src/dotty/tools/dotc/core/Types.scala @@ -745,9 +745,9 @@ object Types { override def computeHash = doHash(name, prefix) } - abstract case class TermRef(override val prefix: Type, name: TermName) extends NamedType with SingletonType + sealed abstract case class TermRef(override val prefix: Type, name: TermName) extends NamedType with SingletonType - abstract case class TypeRef(override val prefix: Type, name: TypeName) extends NamedType + sealed abstract case class TypeRef(override val prefix: Type, name: TypeName) extends NamedType trait HasFixedSym extends NamedType { protected val fixedSym: Symbol @@ -803,7 +803,7 @@ object Types { // --- Other SingletonTypes: ThisType/SuperType/ConstantType --------------------------- - abstract case class ThisType(cls: ClassSymbol) extends CachedProxyType with SingletonType { + sealed abstract case class ThisType(cls: ClassSymbol) extends CachedProxyType with SingletonType { override def underlying(implicit ctx: Context) = cls.selfType override def computeHash = doHash(cls) } @@ -817,7 +817,7 @@ object Types { } } - abstract case class SuperType(thistpe: Type, supertpe: Type) extends CachedProxyType with SingletonType { + sealed abstract case class SuperType(thistpe: Type, supertpe: Type) extends CachedProxyType with SingletonType { override def underlying(implicit ctx: Context) = supertpe def derivedSuperType(thistp: Type, supertp: Type)(implicit ctx: Context) = if ((thistp eq thistpe) && (supertp eq supertpe)) this @@ -832,7 +832,7 @@ object Types { unique(new CachedSuperType(thistpe, supertpe)) } - abstract case class ConstantType(value: Constant) extends CachedProxyType with SingletonType { + sealed abstract case class ConstantType(value: Constant) extends CachedProxyType with SingletonType { override def underlying(implicit ctx: Context) = value.tpe override def computeHash = doHash(value) } @@ -846,7 +846,7 @@ object Types { // --- Refined Type --------------------------------------------------------- - abstract case class RefinedType(parent: Type, name: Name)(infof: RefinedType => Type) extends CachedProxyType with BindingType { + sealed abstract case class RefinedType(parent: Type, name: Name)(infof: RefinedType => Type) extends CachedProxyType with BindingType { val info: Type = infof(this) @@ -875,7 +875,7 @@ object Types { // --- AndType/OrType --------------------------------------------------------------- - abstract case class AndType(tp1: Type, tp2: Type) extends CachedGroundType { + sealed abstract case class AndType(tp1: Type, tp2: Type) extends CachedGroundType { type This <: AndType @@ -893,7 +893,7 @@ object Types { unique(new CachedAndType(tp1, tp2)) } - abstract case class OrType(tp1: Type, tp2: Type) extends CachedGroundType { + sealed abstract case class OrType(tp1: Type, tp2: Type) extends CachedGroundType { def derivedOrType(t1: Type, t2: Type)(implicit ctx: Context) = if ((t1 eq tp1) && (t2 eq tp2)) this else OrType(t1, t2) @@ -916,7 +916,7 @@ object Types { // The reason is that most poly types are cyclic via poly params, // and therefore two different poly types would never be equal. - abstract case class MethodType(paramNames: List[TermName], paramTypes: List[Type])(resultTypeExp: MethodType => Type) extends CachedGroundType with BindingType { + sealed abstract case class MethodType(paramNames: List[TermName], paramTypes: List[Type])(resultTypeExp: MethodType => Type) extends CachedGroundType with BindingType { override lazy val resultType = resultTypeExp(this) def isJava = false def isImplicit = false @@ -988,7 +988,7 @@ object Types { unique(new ImplicitMethodType(paramNames, paramTypes)(resultTypeExp)) } - abstract case class ExprType(override val resultType: Type) extends CachedProxyType { + sealed abstract case class ExprType(override val resultType: Type) extends CachedProxyType { override def underlying(implicit ctx: Context): Type = resultType override def signature: Signature = Nil def derivedExprType(rt: Type)(implicit ctx: Context) = @@ -1003,7 +1003,7 @@ object Types { unique(new CachedExprType(resultType)) } - case class PolyType(paramNames: List[TypeName])(paramBoundsExp: PolyType => List[TypeBounds], resultTypeExp: PolyType => Type) + final case class PolyType(paramNames: List[TypeName])(paramBoundsExp: PolyType => List[TypeBounds], resultTypeExp: PolyType => Type) extends UncachedGroundType with BindingType { lazy val paramBounds = paramBoundsExp(this) override lazy val resultType = resultTypeExp(this) @@ -1048,21 +1048,21 @@ object Types { def copy(bt: BT): Type } - case class MethodParam(binder: MethodType, paramNum: Int) extends BoundType with SingletonType { + final case class MethodParam(binder: MethodType, paramNum: Int) extends BoundType with SingletonType { type BT = MethodType override def underlying(implicit ctx: Context) = binder.paramTypes(paramNum) override def hashCode = doHash(System.identityHashCode(binder) + paramNum) def copy(bt: BT) = MethodParam(bt, paramNum) } - case class PolyParam(binder: PolyType, paramNum: Int) extends BoundType { + final case class PolyParam(binder: PolyType, paramNum: Int) extends BoundType { type BT = PolyType override def underlying(implicit ctx: Context) = binder.paramBounds(paramNum).hi def copy(bt: BT) = PolyParam(bt, paramNum) // no hashCode needed because cycle is broken in PolyType } - case class RefinedThis(binder: RefinedType) extends BoundType with SingletonType { + final case class RefinedThis(binder: RefinedType) extends BoundType with SingletonType { type BT = RefinedType override def underlying(implicit ctx: Context) = binder.parent def copy(bt: BT) = RefinedThis(bt) @@ -1071,7 +1071,7 @@ object Types { // ------ ClassInfo, Type Bounds ------------------------------------------------------------ - abstract case class ClassInfo(prefix: Type, classd: ClassDenotation) extends CachedGroundType with TypeType { + sealed abstract case class ClassInfo(prefix: Type, classd: ClassDenotation) extends CachedGroundType with TypeType { /* def typeTemplate(implicit ctx: Context): Type = classd.typeTemplate asSeenFrom (prefix, classd.symbol) @@ -1098,7 +1098,7 @@ object Types { unique(new CachedClassInfo(prefix, classd)) } - abstract case class TypeBounds(lo: Type, hi: Type) extends CachedProxyType with TypeType { + sealed abstract case class TypeBounds(lo: Type, hi: Type) extends CachedProxyType with TypeType { override def underlying(implicit ctx: Context): Type = hi def derivedTypeBounds(lo1: Type, hi1: Type)(implicit ctx: Context) = if ((lo1 eq lo) && (hi1 eq hi)) this @@ -1140,7 +1140,7 @@ object Types { // ----- Annotated and Import types ----------------------------------------------- - case class AnnotatedType(annots: List[Annotation], tpe: Type) extends UncachedProxyType { + final case class AnnotatedType(annots: List[Annotation], tpe: Type) extends UncachedProxyType { override def underlying(implicit ctx: Context): Type = tpe def derivedAnnotatedType(annots1: List[Annotation], tpe1: Type) = if ((annots1 eq annots) && (tpe1 eq tpe)) this @@ -1153,7 +1153,7 @@ object Types { else AnnotatedType(annots, underlying) } - case class ImportType(expr: TypedTree) extends UncachedGroundType + final case class ImportType(expr: TypedTree) extends UncachedGroundType // Special type objects ------------------------------------------------------------ From 6a263df2ffa5617dda6865ae05e2b67ccebf6cfa Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Sat, 23 Feb 2013 01:06:28 +0100 Subject: [PATCH 04/22] Make more classes final. --- src/dotty/tools/dotc/config/Settings.scala | 4 ++-- src/dotty/tools/dotc/core/Annotations.scala | 2 +- src/dotty/tools/dotc/core/Constants.scala | 2 +- src/dotty/tools/dotc/core/Denotations.scala | 4 ++-- src/dotty/tools/dotc/core/Flags.scala | 2 +- src/dotty/tools/dotc/core/Trees.scala | 2 +- src/dotty/tools/dotc/core/pickling/ClassfileParser.scala | 2 +- src/dotty/tools/dotc/core/pickling/UnPickler.scala | 4 ++-- 8 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/dotty/tools/dotc/config/Settings.scala b/src/dotty/tools/dotc/config/Settings.scala index c1ac1f83a53d..3572a28dd0aa 100644 --- a/src/dotty/tools/dotc/config/Settings.scala +++ b/src/dotty/tools/dotc/config/Settings.scala @@ -33,7 +33,7 @@ object Settings { } } - case class ArgsSummary( + final case class ArgsSummary( sstate: SettingsState, arguments: List[String], errors: List[String]) { @@ -42,7 +42,7 @@ object Settings { ArgsSummary(sstate, arguments, errors :+ msg) } - case class Setting[T: ClassTag] private[Settings] ( + final case class Setting[T: ClassTag] private[Settings] ( name: String, description: String, default: T, diff --git a/src/dotty/tools/dotc/core/Annotations.scala b/src/dotty/tools/dotc/core/Annotations.scala index 2ced6cb8a462..681fdab22c94 100644 --- a/src/dotty/tools/dotc/core/Annotations.scala +++ b/src/dotty/tools/dotc/core/Annotations.scala @@ -11,7 +11,7 @@ object Annotations { def appliesToModule: Boolean = ??? } - case class ConcreteAnnotation(val tree: Tree) extends Annotation + final case class ConcreteAnnotation(val tree: Tree) extends Annotation object Annotation { diff --git a/src/dotty/tools/dotc/core/Constants.scala b/src/dotty/tools/dotc/core/Constants.scala index 825ce60f1f2e..616124004a0e 100644 --- a/src/dotty/tools/dotc/core/Constants.scala +++ b/src/dotty/tools/dotc/core/Constants.scala @@ -21,7 +21,7 @@ object Constants { // For supporting java enumerations inside java annotations (see ClassfileParser) final val EnumTag = 13 - case class Constant(value: Any) { + final case class Constant(value: Any) { import java.lang.Double.doubleToRawLongBits import java.lang.Float.floatToRawIntBits diff --git a/src/dotty/tools/dotc/core/Denotations.scala b/src/dotty/tools/dotc/core/Denotations.scala index c7c257f5cc81..b07de8ebf6c8 100644 --- a/src/dotty/tools/dotc/core/Denotations.scala +++ b/src/dotty/tools/dotc/core/Denotations.scala @@ -284,7 +284,7 @@ object Denotations { /** The class of overloaded denotations * @param variants The overloaded variants indexed by thheir signatures. */ - case class MultiDenotation(denot1: Denotation, denot2: Denotation) extends Denotation { + final case class MultiDenotation(denot1: Denotation, denot2: Denotation) extends Denotation { final override def isType = false def derivedMultiDenotation(d1: Denotation, d2: Denotation) = if ((d1 eq denot1) && (d2 eq denot2)) this else MultiDenotation(d1, d2) @@ -475,7 +475,7 @@ object Denotations { else DenotUnion(this, that) } - case class DenotUnion(denots1: DenotationSet, denots2: DenotationSet) extends DenotationSet { + final case class DenotUnion(denots1: DenotationSet, denots2: DenotationSet) extends DenotationSet { assert(denots1.exists && denots2.exists) private def derivedUnion(s1: DenotationSet, s2: DenotationSet) = if (!s1.exists) s2 diff --git a/src/dotty/tools/dotc/core/Flags.scala b/src/dotty/tools/dotc/core/Flags.scala index 710771fa5075..a527fbafc675 100644 --- a/src/dotty/tools/dotc/core/Flags.scala +++ b/src/dotty/tools/dotc/core/Flags.scala @@ -105,7 +105,7 @@ object Flags { * conjunctively. I.e. for a flag conjunction `fc`, * `x is fc` tests whether `x` contains all flags in `fc`. */ - case class FlagConjunction(bits: Long) + final case class FlagConjunction(bits: Long) private final val TYPESHIFT = 2 private final val TERMindex = 0 diff --git a/src/dotty/tools/dotc/core/Trees.scala b/src/dotty/tools/dotc/core/Trees.scala index 9a842c71faad..384a44ef42c7 100644 --- a/src/dotty/tools/dotc/core/Trees.scala +++ b/src/dotty/tools/dotc/core/Trees.scala @@ -6,7 +6,7 @@ import annotation.tailrec object Trees { - case class Modifiers[T]( + final case class Modifiers[T]( flags: FlagSet, privateWithin: TypeName = tpnme.EMPTY, annotations: List[Tree[T]] = Nil) diff --git a/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala b/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala index 2f370fbddfe8..0aba91fea3e2 100644 --- a/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala +++ b/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala @@ -608,7 +608,7 @@ class ClassfileParser( } /** An entry in the InnerClasses attribute of this class file. */ - case class InnerClassEntry(external: Int, outer: Int, name: Int, jflags: Int) { + final case class InnerClassEntry(external: Int, outer: Int, name: Int, jflags: Int) { def externalName = pool.getClassName(external) def outerName = pool.getClassName(outer) def originalName = pool.getName(name) diff --git a/src/dotty/tools/dotc/core/pickling/UnPickler.scala b/src/dotty/tools/dotc/core/pickling/UnPickler.scala index 71601fedf7de..1145b264d5f5 100644 --- a/src/dotty/tools/dotc/core/pickling/UnPickler.scala +++ b/src/dotty/tools/dotc/core/pickling/UnPickler.scala @@ -21,10 +21,10 @@ object UnPickler { /** Exception thrown if classfile is corrupted */ class BadSignature(msg: String) extends RuntimeException(msg) - case class TempPolyType(tparams: List[Symbol], tpe: Type) extends UncachedGroundType + final case class TempPolyType(tparams: List[Symbol], tpe: Type) extends UncachedGroundType /** Temporary type for classinfos, will be decomposed on completion of the class */ - case class TempClassInfoType(parentTypes: List[Type], decls: Scope, clazz: Symbol) extends UncachedGroundType + final case class TempClassInfoType(parentTypes: List[Type], decls: Scope, clazz: Symbol) extends UncachedGroundType def depoly(tp: Type)(implicit ctx: Context): Type = tp match { case TempPolyType(tparams, restpe) => PolyType.fromSymbols(tparams, restpe) From 90df1e662fa59f75f6d7a5dcfe1fc8562e7a265d Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Sat, 23 Feb 2013 01:10:18 +0100 Subject: [PATCH 05/22] seal / finalize Contexts. --- src/dotty/tools/dotc/core/Contexts.scala | 28 ++++++++++++------------ 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/dotty/tools/dotc/core/Contexts.scala b/src/dotty/tools/dotc/core/Contexts.scala index 9ca111dc0468..6b1375406c35 100644 --- a/src/dotty/tools/dotc/core/Contexts.scala +++ b/src/dotty/tools/dotc/core/Contexts.scala @@ -35,12 +35,12 @@ object Contexts { * of all class fields of type context; allow them only in whitelisted * classes (which should be short-lived). */ - abstract class Context extends Periods - with Substituters - with TypeOps - with Printers - with Symbols - with Cloneable { + sealed abstract class Context extends Periods + with Substituters + with TypeOps + with Printers + with Symbols + with Cloneable { implicit val ctx: Context = this val base: ContextBase @@ -120,9 +120,9 @@ object Contexts { } } - abstract class CondensedContext extends Context + sealed abstract class CondensedContext extends Context - abstract class FreshContext extends CondensedContext { + sealed abstract class FreshContext extends CondensedContext { def withPeriod(period: Period): this.type = { this.period = period; this } def withPhase(pid: PhaseId): this.type = withPeriod(Period(runId, pid)) def withConstraints(constraints: Constraints): this.type = { this.constraints = constraints; this } @@ -133,7 +133,7 @@ object Contexts { def withDiagnostics(diagnostics: Option[StringBuilder]): this.type = { this.diagnostics = diagnostics; this } } - private class InitialContext(val base: ContextBase) extends FreshContext { + private final class InitialContext(val base: ContextBase) extends FreshContext { underlying = NoContext period = Nowhere constraints = Map() @@ -146,10 +146,10 @@ object Contexts { lazy val base = unsupported("base") } - class ContextBase extends ContextState - with Transformers.TransformerBase - with Printers.PrinterBase - with Denotations.DenotationsBase { + final class ContextBase extends ContextState + with Transformers.TransformerBase + with Printers.PrinterBase + with Denotations.DenotationsBase { val settings = new ScalaSettings @@ -167,7 +167,7 @@ object Contexts { } /** Mutable state of a context base, collected into a common class */ - class ContextState { + abstract class ContextState { // Symbols state From 8cc097ec298205c05bd684ad6513056815a457b9 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Sat, 23 Feb 2013 01:22:53 +0100 Subject: [PATCH 06/22] More Modifier lock down in Contexts. --- src/dotty/tools/dotc/core/Contexts.scala | 118 +++++++++++------------ 1 file changed, 59 insertions(+), 59 deletions(-) diff --git a/src/dotty/tools/dotc/core/Contexts.scala b/src/dotty/tools/dotc/core/Contexts.scala index 6b1375406c35..3aae8ed890b4 100644 --- a/src/dotty/tools/dotc/core/Contexts.scala +++ b/src/dotty/tools/dotc/core/Contexts.scala @@ -41,68 +41,68 @@ object Contexts { with Printers with Symbols with Cloneable { - implicit val ctx: Context = this + final implicit val ctx: Context = this val base: ContextBase - private[this] var _underlying: Context = _ - protected def underlying_=(underlying: Context) = _underlying = underlying - def underlying: Context = _underlying + final private[this] var _underlying: Context = _ + protected final def underlying_=(underlying: Context) = _underlying = underlying + final def underlying: Context = _underlying - private[this] var _period: Period = _ - protected def period_=(period: Period) = _period = period - def period: Period = _period + final private[this] var _period: Period = _ + protected final def period_=(period: Period) = _period = period + final def period: Period = _period - private[this] var _constraints: Constraints = _ - protected def constraints_=(constraints: Constraints) = _constraints = constraints - def constraints: Constraints = _constraints + final private[this] var _constraints: Constraints = _ + protected final def constraints_=(constraints: Constraints) = _constraints = constraints + final def constraints: Constraints = _constraints - private[this] var _typeComparer: TypeComparer = _ - protected def typeComparer_=(typeComparer: TypeComparer) = _typeComparer = typeComparer + final private[this] var _typeComparer: TypeComparer = _ + protected final def typeComparer_=(typeComparer: TypeComparer) = _typeComparer = typeComparer - def typeComparer: TypeComparer = { + final def typeComparer: TypeComparer = { if ((_typeComparer eq underlying.typeComparer) && (constraints ne underlying.constraints)) _typeComparer = new TypeComparer(this) _typeComparer } - private[this] var _position: Position = _ - protected def position_=(position: Position) = _position = position - def position: Position = _position + final private[this] var _position: Position = _ + protected final def position_=(position: Position) = _position = position + final def position: Position = _position private[this] var _plainPrinter: Context => Printer = _ - protected def plainPrinter_=(plainPrinter: Context => Printer) = _plainPrinter = plainPrinter - def plainPrinter: Context => Printer = _plainPrinter + protected final def plainPrinter_=(plainPrinter: Context => Printer) = _plainPrinter = plainPrinter + final def plainPrinter: Context => Printer = _plainPrinter private[this] var _refinedPrinter: Context => Printer = _ - protected def refinedPrinter_=(refinedPrinter: Context => Printer) = _refinedPrinter = refinedPrinter - def refinedPrinter: Context => Printer = _refinedPrinter + protected final def refinedPrinter_=(refinedPrinter: Context => Printer) = _refinedPrinter = refinedPrinter + final def refinedPrinter: Context => Printer = _refinedPrinter - def printer = if (base.settings.debug.value) plainPrinter else refinedPrinter + final def printer = if (base.settings.debug.value) plainPrinter else refinedPrinter private[this] var _owner: Symbol = _ - protected def owner_=(owner: Symbol) = _owner = owner - def owner: Symbol = _owner + protected final def owner_=(owner: Symbol) = _owner = owner + final def owner: Symbol = _owner private[this] var _sstate: SettingsState = _ - protected def sstate_=(sstate: SettingsState) = _sstate = sstate - def sstate: SettingsState = _sstate - - def phase: Phase = ??? // phase(period.phaseId) - def enclClass: Context = ??? - def erasedTypes: Boolean = ??? - def debug: Boolean = ??? - def error(msg: String): Unit = ??? - def warning(msg: String): Unit = ??? - def log(msg: String): Unit = ??? - def debuglog(msg: String): Unit = ??? - def inform(msg: String) = ??? - def informTime(msg: String, start: Long): Unit = ??? - def beforeTyper[T](op: => T): T = ??? - - private var _condensed: CondensedContext = null - def condensed: CondensedContext = { + protected final def sstate_=(sstate: SettingsState) = _sstate = sstate + final def sstate: SettingsState = _sstate + + final def phase: Phase = ??? // phase(period.phaseId) + final def enclClass: Context = ??? + final def erasedTypes: Boolean = ??? + final def debug: Boolean = ??? + final def error(msg: String): Unit = ??? + final def warning(msg: String): Unit = ??? + final def log(msg: String): Unit = ??? + final def debuglog(msg: String): Unit = ??? + final def inform(msg: String) = ??? + final def informTime(msg: String, start: Long): Unit = ??? + final def beforeTyper[T](op: => T): T = ??? + + private final var _condensed: CondensedContext = null + final def condensed: CondensedContext = { if (_condensed == null) _condensed = base.initialCtx.fresh .withPeriod(period) @@ -112,7 +112,7 @@ object Contexts { _condensed } - def fresh: FreshContext = { + final def fresh: FreshContext = { val newctx = super.clone.asInstanceOf[FreshContext] newctx.underlying = this newctx._condensed = null @@ -123,14 +123,14 @@ object Contexts { sealed abstract class CondensedContext extends Context sealed abstract class FreshContext extends CondensedContext { - def withPeriod(period: Period): this.type = { this.period = period; this } - def withPhase(pid: PhaseId): this.type = withPeriod(Period(runId, pid)) - def withConstraints(constraints: Constraints): this.type = { this.constraints = constraints; this } - def withPlainPrinter(printer: Context => Printer): this.type = { this.plainPrinter = printer; this } - def withRefinedPrinter(printer: Context => Printer): this.type = { this.refinedPrinter = printer; this } - def withOwner(owner: Symbol): this.type = { this.owner = owner; this } - def withSettings(sstate: SettingsState): this.type = { this.sstate = sstate; this } - def withDiagnostics(diagnostics: Option[StringBuilder]): this.type = { this.diagnostics = diagnostics; this } + final def withPeriod(period: Period): this.type = { this.period = period; this } + final def withPhase(pid: PhaseId): this.type = withPeriod(Period(runId, pid)) + final def withConstraints(constraints: Constraints): this.type = { this.constraints = constraints; this } + final def withPlainPrinter(printer: Context => Printer): this.type = { this.plainPrinter = printer; this } + final def withRefinedPrinter(printer: Context => Printer): this.type = { this.refinedPrinter = printer; this } + final def withOwner(owner: Symbol): this.type = { this.owner = owner; this } + final def withSettings(sstate: SettingsState): this.type = { this.sstate = sstate; this } + final def withDiagnostics(diagnostics: Option[StringBuilder]): this.type = { this.diagnostics = diagnostics; this } } private final class InitialContext(val base: ContextBase) extends FreshContext { @@ -172,21 +172,21 @@ object Contexts { // Symbols state /** A counter for unique ids */ - private[core] var _nextId = 0 + private[core] final var _nextId = 0 - def nextId = { _nextId += 1; _nextId } + final def nextId = { _nextId += 1; _nextId } /** A map from a superclass id to the type-ref of the class that has it */ - private[core] var classOfId = new Array[TypeRef](InitialSuperIdsSize) + private[core] final var classOfId = new Array[TypeRef](InitialSuperIdsSize) /** A map from a the type-ref of a superclass to its superclass id */ - private[core] val superIdOfClass = new mutable.HashMap[TypeRef, Int] + private[core] final val superIdOfClass = new mutable.HashMap[TypeRef, Int] /** The last allocate superclass id */ - private[core] var lastSuperId = -1 + private[core] final var lastSuperId = -1 /** Allocate and return next free superclass id */ - private[core] def nextSuperId: Int = { + private[core] final def nextSuperId: Int = { lastSuperId += 1; if (lastSuperId >= classOfId.length) { val tmp = new Array[TypeRef](classOfId.length * 2) @@ -197,16 +197,16 @@ object Contexts { } // SymDenotations state - private[core] val uniqueBits = new util.HashSet[BitSet]("superbits", 1024) + private[core] final val uniqueBits = new util.HashSet[BitSet]("superbits", 1024) // Types state - private[core] val uniques = new util.HashSet[Type]("uniques", initialUniquesCapacity) { + private[core] final val uniques = new util.HashSet[Type]("uniques", initialUniquesCapacity) { override def hash(x: Type): Int = x.hash } // TypeOps state - private[core] var volatileRecursions: Int = 0 - private[core] val pendingVolatiles = new mutable.HashSet[Type] + private[core] final var volatileRecursions: Int = 0 + private[core] final val pendingVolatiles = new mutable.HashSet[Type] } object Context { From 1c247ec3e0c1df017c42aaa5998e5ed6a285f2d1 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Sat, 23 Feb 2013 01:25:17 +0100 Subject: [PATCH 07/22] More Modifier lock down in Annotations. --- src/dotty/tools/dotc/core/Annotations.scala | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/dotty/tools/dotc/core/Annotations.scala b/src/dotty/tools/dotc/core/Annotations.scala index 681fdab22c94..f7c66099069d 100644 --- a/src/dotty/tools/dotc/core/Annotations.scala +++ b/src/dotty/tools/dotc/core/Annotations.scala @@ -4,14 +4,14 @@ import Symbols._, Types._, Positions._, Contexts._, Constants._, TypedTrees.tpd. object Annotations { - abstract class Annotation { + sealed abstract class Annotation { def tree: Tree - def symbol(implicit ctx: Context): Symbol = tree.tpe.typeSymbol - def matches(cls: Symbol)(implicit ctx: Context): Boolean = symbol.isNonBottomSubClass(cls) - def appliesToModule: Boolean = ??? + final def symbol(implicit ctx: Context): Symbol = tree.tpe.typeSymbol + final def matches(cls: Symbol)(implicit ctx: Context): Boolean = symbol.isNonBottomSubClass(cls) + final def appliesToModule: Boolean = ??? } - final case class ConcreteAnnotation(val tree: Tree) extends Annotation + final case class ConcreteAnnotation(tree: Tree) extends Annotation object Annotation { From d50acb4dd701467373ee007bb133a1135f8d7257 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Sat, 23 Feb 2013 01:27:12 +0100 Subject: [PATCH 08/22] More Modifier lock down in Definitions. --- src/dotty/tools/dotc/core/Definitions.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dotty/tools/dotc/core/Definitions.scala b/src/dotty/tools/dotc/core/Definitions.scala index 935369091588..ad511217f467 100644 --- a/src/dotty/tools/dotc/core/Definitions.scala +++ b/src/dotty/tools/dotc/core/Definitions.scala @@ -19,7 +19,7 @@ object Definitions { val MaxFunctionArity, MaxTupleArity = 22 } -class Definitions(implicit ctx: Context) { +final class Definitions(implicit ctx: Context) { import Definitions._ import ctx.{requiredClass, requiredModule, requiredPackage} From fc898f68f1583c3226485777467762e08f89ad43 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Sat, 23 Feb 2013 01:34:20 +0100 Subject: [PATCH 09/22] More modifier lock down in Denotations. --- src/dotty/tools/dotc/core/Denotations.scala | 70 ++++++++++----------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/src/dotty/tools/dotc/core/Denotations.scala b/src/dotty/tools/dotc/core/Denotations.scala index b07de8ebf6c8..b5560d12976a 100644 --- a/src/dotty/tools/dotc/core/Denotations.scala +++ b/src/dotty/tools/dotc/core/Denotations.scala @@ -120,7 +120,7 @@ object Denotations { * * Then the denotation of `y` is `SingleDenotation(NoSymbol, A | B)`. */ - abstract class Denotation extends DotClass { + sealed abstract class Denotation extends DotClass { /** The referencing symbol, exists only for non-overloaded denotations */ def symbol: Symbol @@ -155,10 +155,10 @@ object Denotations { def exists: Boolean = true - def orElse(that: => Denotation) = if (this.exists) this else that + final def orElse(that: => Denotation) = if (this.exists) this else that /** The set of alternative single-denotations making up this denotation */ - def alts(p: Symbol => Boolean)(implicit ctx: Context): List[SingleDenotation] = + final def alts(p: Symbol => Boolean)(implicit ctx: Context): List[SingleDenotation] = altsWith(scala.Function.const(true)) /** The alternatives of this denotation that satisfy the predicate `p`. */ @@ -179,7 +179,7 @@ object Denotations { * single-denotations that do not satisfy the predicate are left alone * (whereas suchThat would map them to NoDenotation). */ - def disambiguate(p: Symbol => Boolean)(implicit ctx: Context): SingleDenotation = this match { + final def disambiguate(p: Symbol => Boolean)(implicit ctx: Context): SingleDenotation = this match { case sdenot: SingleDenotation => sdenot case mdenot => suchThat(p) } @@ -188,7 +188,7 @@ object Denotations { * Throw a `TypeError` if predicate fails to disambiguate symbol. * Return a stubsymbol if no alternative satisfies the predicate. */ - def requiredSymbol(p: Symbol => Boolean, source: AbstractFile = null)(implicit ctx: Context): Symbol = { + final def requiredSymbol(p: Symbol => Boolean, source: AbstractFile = null)(implicit ctx: Context): Symbol = { val sym = disambiguate(p).symbol if (sym.exists) sym else { val owner = if (firstSym.exists) firstSym.owner else NoSymbol @@ -197,7 +197,7 @@ object Denotations { } /** Form a denotation by conjoining with denotation `that` */ - def &(that: Denotation)(implicit ctx: Context): Denotation = + final def &(that: Denotation)(implicit ctx: Context): Denotation = if (this eq that) this else if (!this.exists) that else if (!that.exists) this @@ -241,7 +241,7 @@ object Denotations { } else NoDenotation } - def |(that: Denotation)(pre: Type)(implicit ctx: Context): Denotation = { + final def |(that: Denotation)(pre: Type)(implicit ctx: Context): Denotation = { def lubSym(sym1: Symbol, sym2: Symbol): Symbol = { def qualifies(sym: Symbol) = @@ -278,7 +278,7 @@ object Denotations { } } - def show(implicit ctx: Context): String = ctx.show(this) + final def show(implicit ctx: Context): String = ctx.show(this) } /** The class of overloaded denotations @@ -312,8 +312,8 @@ object Denotations { } abstract class SingleDenotation extends Denotation with DenotationSet { - override def isType = info.isInstanceOf[TypeType] - override def signature: Signature = { + def isType = info.isInstanceOf[TypeType] + override final def signature: Signature = { def sig(tp: Type): Signature = tp match { case tp: PolyType => tp.resultType match { @@ -325,33 +325,33 @@ object Denotations { } if (isType) NullSignature else sig(info) } - def firstSym(implicit ctx: Context): Symbol = symbol + final def firstSym(implicit ctx: Context): Symbol = symbol - def derivedSingleDenotation(s: Symbol, i: Type): SingleDenotation = + final def derivedSingleDenotation(s: Symbol, i: Type): SingleDenotation = if ((s eq symbol) && (i eq info)) this else newLikeThis(s, i) protected def newLikeThis(s: Symbol, i: Type): SingleDenotation = this - def orElse(that: => SingleDenotation) = if (this.exists) this else that + final def orElse(that: => SingleDenotation) = if (this.exists) this else that - def altsWith(p: Symbol => Boolean)(implicit ctx: Context): List[SingleDenotation] = + final def altsWith(p: Symbol => Boolean)(implicit ctx: Context): List[SingleDenotation] = if (p(symbol)) this :: Nil else Nil - def suchThat(p: Symbol => Boolean)(implicit ctx: Context): SingleDenotation = + final def suchThat(p: Symbol => Boolean)(implicit ctx: Context): SingleDenotation = if (p(symbol)) this else NoDenotation - def hasAltWith(p: Symbol => Boolean)(implicit ctx: Context): Boolean = + final def hasAltWith(p: Symbol => Boolean)(implicit ctx: Context): Boolean = p(symbol) - def atSignature(sig: Signature): SingleDenotation = + final def atSignature(sig: Signature): SingleDenotation = if (sig == signature) this else NoDenotation // ------ Transformations ----------------------------------------- private[this] var _validFor: Period = Nowhere - def validFor = _validFor - def validFor_=(p: Period) = + final def validFor = _validFor + final def validFor_=(p: Period) = _validFor = p /** The next SingleDenotation in this run, with wrap-around from last to first. @@ -368,18 +368,18 @@ object Denotations { * 2) the union of all validity periods must be a contiguous * interval starting in FirstPhaseId. */ - var nextInRun: SingleDenotation = this + final var nextInRun: SingleDenotation = this /** The version of this SingleDenotation that was valid in the first phase * of this run. */ - def initial: SingleDenotation = { + final def initial: SingleDenotation = { var current = nextInRun while (current.validFor.code > this._validFor.code) current = current.nextInRun current } - def current(implicit ctx: Context): SingleDenotation = { + final def current(implicit ctx: Context): SingleDenotation = { val currentPeriod = ctx.period val valid = _validFor var current = this @@ -421,35 +421,35 @@ object Denotations { // ------ DenotationSet ops ---------------------------------------------- - def first = this - def toDenot(implicit ctx: Context) = this - def containsSig(sig: Signature)(implicit ctx: Context) = + final def first = this + final def toDenot(implicit ctx: Context) = this + final def containsSig(sig: Signature)(implicit ctx: Context) = signature == sig - def filterDisjoint(denots: DenotationSet)(implicit ctx: Context): DenotationSet = + final def filterDisjoint(denots: DenotationSet)(implicit ctx: Context): DenotationSet = if (denots.containsSig(signature)) NoDenotation else this - def filterExcluded(flags: FlagSet)(implicit ctx: Context): DenotationSet = + final def filterExcluded(flags: FlagSet)(implicit ctx: Context): DenotationSet = if (symbol is flags) NoDenotation else this - def filterAccessibleFrom(pre: Type)(implicit ctx: Context): DenotationSet = + final def filterAccessibleFrom(pre: Type)(implicit ctx: Context): DenotationSet = if (symbol.isAccessibleFrom(pre)) this else NoDenotation - def asSeenFrom(pre: Type, owner: Symbol)(implicit ctx: Context): DenotationSet = + final def asSeenFrom(pre: Type, owner: Symbol)(implicit ctx: Context): DenotationSet = derivedSingleDenotation(symbol, info.asSeenFrom(pre, owner)) } - class UniqueRefDenotation(val symbol: Symbol, + final class UniqueRefDenotation(val symbol: Symbol, val info: Type, initValidFor: Period) extends SingleDenotation { validFor = initValidFor override protected def newLikeThis(s: Symbol, i: Type): SingleDenotation = new UniqueRefDenotation(s, i, validFor) } - class JointRefDenotation(val symbol: Symbol, + final class JointRefDenotation(val symbol: Symbol, val info: Type, initValidFor: Period) extends SingleDenotation { validFor = initValidFor override protected def newLikeThis(s: Symbol, i: Type): SingleDenotation = new JointRefDenotation(s, i, validFor) } - class ErrorDenotation(implicit ctx: Context) extends SingleDenotation { + final class ErrorDenotation(implicit ctx: Context) extends SingleDenotation { val symbol = NoSymbol val info = NoType validFor = Period.allInRun(ctx.runId) @@ -469,7 +469,7 @@ object Denotations { def filterExcluded(flags: FlagSet)(implicit ctx: Context): DenotationSet def filterAccessibleFrom(pre: Type)(implicit ctx: Context): DenotationSet def asSeenFrom(pre: Type, owner: Symbol)(implicit ctx: Context): DenotationSet - def union(that: DenotationSet) = + final def union(that: DenotationSet) = if (!this.exists) that else if (that.exists) this else DenotUnion(this, that) @@ -501,7 +501,7 @@ object Denotations { /** Creation method for denotations */ trait DenotationsBase { this: ContextBase => - def staticRef(path: Name)(implicit ctx: Context): Denotation = { + final def staticRef(path: Name)(implicit ctx: Context): Denotation = { def recur(path: Name, len: Int): Denotation = { val point = path.lastIndexOf('.', len - 1) val owner = @@ -523,7 +523,7 @@ object Denotations { recur(path, path.length) } - def missingHook(owner: Symbol, name: Name)(implicit ctx: Context): Symbol = + final def missingHook(owner: Symbol, name: Name)(implicit ctx: Context): Symbol = if (owner.isPackage && name.isTermName) ctx.newPackageSymbols(owner, name.asTermName)._1.entered else From 88b1ac4da96ad8a7eb11aeaa4efbf06bd0df520a Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Sat, 23 Feb 2013 01:42:24 +0100 Subject: [PATCH 10/22] More modifier lock down in Names. --- src/dotty/tools/dotc/core/Names.scala | 62 +++++++++++++-------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/src/dotty/tools/dotc/core/Names.scala b/src/dotty/tools/dotc/core/Names.scala index 8a13964e34ed..d9759857728d 100644 --- a/src/dotty/tools/dotc/core/Names.scala +++ b/src/dotty/tools/dotc/core/Names.scala @@ -21,12 +21,12 @@ object Names { /** A name is essentially a string, with three differences * 1. Names belong in one of two universes: they are type names or term names. * The same string can correspond both to a type name and to a term name. - * 2. NAmes are hash-consed. Two names + * 2. Names are hash-consed. Two names * representing the same string in the same universe are always reference identical. * 3. Names are intended to be encoded strings. @see dotc.util.NameTransformer. * The encoding will be applied when converting a string to a name. */ - abstract class Name extends DotClass + sealed abstract class Name extends DotClass with PreName with Seq[Char] with IndexedSeqOptimized[Char, Name] { @@ -65,7 +65,7 @@ object Names { */ def fromChars(cs: Array[Char], offset: Int, len: Int): ThisName - override def toString = new String(chrs, start, length) + override final def toString = new String(chrs, start, length) /** Write to UTF8 representation of this name to given character array. * Start copying to index `to`. Return index of next free byte in array. @@ -79,16 +79,16 @@ object Names { } /** Convert to string replacing operator symbols by corresponding \$op_name. */ - def decode: String = NameTransformer.decode(toString) + final def decode: String = NameTransformer.decode(toString) - def ++ (other: Name): ThisName = ++ (other.toString) + final def ++ (other: Name): ThisName = ++ (other.toString) - def ++ (other: String): ThisName = { + final def ++ (other: String): ThisName = { val s = toString + other fromChars(s.toCharArray, 0, s.length) } - def replace(from: Char, to: Char): ThisName = { + final def replace(from: Char, to: Char): ThisName = { val cs = new Array[Char](length) Array.copy(chrs, start, cs, 0, length) for (i <- 0 until length) { @@ -100,27 +100,27 @@ object Names { // ----- Collections integration ------------------------------------- - override protected[this] def thisCollection: WrappedString = new WrappedString(repr.toString) - override protected[this] def toCollection(repr: Name): WrappedString = new WrappedString(repr.toString) + override protected[this] final def thisCollection: WrappedString = new WrappedString(repr.toString) + override protected[this] final def toCollection(repr: Name): WrappedString = new WrappedString(repr.toString) override protected[this] def newBuilder: Builder[Char, Name] = unsupported("newBuilder") - override def apply(index: Int): Char = chrs(start + index) + override final def apply(index: Int): Char = chrs(start + index) - override def slice(from: Int, until: Int): ThisName = + override final def slice(from: Int, until: Int): ThisName = fromChars(chrs, start + from, start + until) - override def seq = toCollection(this) + override final def seq = toCollection(this) } - class TermName(val start: Int, val length: Int, private[Names] var next: TermName) extends Name { + sealed class TermName(val start: Int, val length: Int, private[Names] var next: TermName) extends Name { type ThisName = TermName - def isTypeName = false - def isTermName = true + final def isTypeName = false + final def isTermName = true @volatile private[this] var _typeName: TypeName = null - def toTypeName: TypeName = { + final def toTypeName: TypeName = { if (_typeName == null) synchronized { if (_typeName == null) @@ -128,35 +128,35 @@ object Names { } _typeName } - def toTermName = this - def asTypeName = throw new ClassCastException(this + " is not a type name") - def asTermName = this + final def toTermName = this + final def asTypeName = throw new ClassCastException(this + " is not a type name") + final def asTermName = this - def toLocalName: LocalName = toTypeName.toLocalName + final def toLocalName: LocalName = toTypeName.toLocalName - override protected[this] def newBuilder: Builder[Char, Name] = termNameBuilder + override protected[this] final def newBuilder: Builder[Char, Name] = termNameBuilder - def fromChars(cs: Array[Char], offset: Int, len: Int): TermName = termName(cs, offset, len) + final def fromChars(cs: Array[Char], offset: Int, len: Int): TermName = termName(cs, offset, len) } class TypeName(val start: Int, val length: Int, initialTermName: TermName) extends Name { type ThisName = TypeName - def isTypeName = true - def isTermName = false - def toTypeName = this - def asTypeName = this - def asTermName = throw new ClassCastException(this + " is not a term name") + final def isTypeName = true + final def isTermName = false + final def toTypeName = this + final def asTypeName = this + final def asTermName = throw new ClassCastException(this + " is not a term name") private[this] var _termName = initialTermName - def toTermName: TermName = _termName match { + final def toTermName: TermName = _termName match { case tn: LocalName => synchronized { tn.toGlobalName } case tn => tn } - def toLocalName: LocalName = _termName match { + final def toLocalName: LocalName = _termName match { case tn: LocalName => tn case _ => @@ -169,7 +169,7 @@ object Names { override protected[this] def newBuilder: Builder[Char, Name] = typeNameBuilder - def fromChars(cs: Array[Char], offset: Int, len: Int): TypeName = typeName(cs, offset, len) + final def fromChars(cs: Array[Char], offset: Int, len: Int): TypeName = typeName(cs, offset, len) } /* A local name representing a field that has otherwise the same name as @@ -198,7 +198,7 @@ object Names { * v | * TypeName */ - class LocalName(start: Int, length: Int, _next: TermName) extends TermName(start, length, _next) { + final class LocalName(start: Int, length: Int, _next: TermName) extends TermName(start, length, _next) { def toGlobalName: TermName = next } From 545e2be9de42dc74bacec076a541c337d6a0df68 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Sat, 23 Feb 2013 01:43:59 +0100 Subject: [PATCH 11/22] More modifier lock down in Periods. --- src/dotty/tools/dotc/core/Periods.scala | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/dotty/tools/dotc/core/Periods.scala b/src/dotty/tools/dotc/core/Periods.scala index 3a91b48cbca4..b1778d4a7238 100644 --- a/src/dotty/tools/dotc/core/Periods.scala +++ b/src/dotty/tools/dotc/core/Periods.scala @@ -11,17 +11,17 @@ abstract class Periods extends DotClass { self: Context => import Periods._ /** The current phase identifier */ - def phaseId = period.phaseId + final def phaseId = period.phaseId /** The current run identifier */ - def runId = period.runId + final def runId = period.runId /** Execute `op` at given period */ - def atPeriod[T](pd: Period)(op: Context => T) = + final def atPeriod[T](pd: Period)(op: Context => T) = op(ctx.fresh.withPeriod(pd)) /** Execute `op` at given phase id */ - def atPhase[T](pid: PhaseId)(op: Context => T) = + final def atPhase[T](pid: PhaseId)(op: Context => T) = op(ctx.fresh.withPhase(pid)) } From 373ab8ca648113e87b6ae4d4b0664fe69642f6db Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Sat, 23 Feb 2013 01:48:56 +0100 Subject: [PATCH 12/22] More modifier lock down in Scopes. --- src/dotty/tools/dotc/core/Scopes.scala | 46 +++++++++++++------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/dotty/tools/dotc/core/Scopes.scala b/src/dotty/tools/dotc/core/Scopes.scala index ee442223dfe0..8a91b8d588d5 100644 --- a/src/dotty/tools/dotc/core/Scopes.scala +++ b/src/dotty/tools/dotc/core/Scopes.scala @@ -29,7 +29,7 @@ object Scopes { */ private final val MaxRecursions = 1000 - class ScopeEntry private[Scopes] (val sym: Symbol, val owner: Scope) { + final class ScopeEntry private[Scopes] (val sym: Symbol, val owner: Scope) { /** the next entry in the hash bucket */ @@ -46,7 +46,7 @@ object Scopes { * This is necessary because when run from reflection every scope needs to have a * SynchronizedScope as mixin. */ - class Scope protected[Scopes](initElems: ScopeEntry, initSize: Int, val nestingLevel: Int = 0) + sealed class Scope protected[Scopes](initElems: ScopeEntry, initSize: Int, val nestingLevel: Int = 0) extends Iterable[Symbol] { protected[Scopes] def this(base: Scope)(implicit ctx: Context) = { @@ -56,12 +56,12 @@ object Scopes { def this() = this(null, 0, 0) - private[dotc] var lastEntry: ScopeEntry = initElems + private[dotc] final var lastEntry: ScopeEntry = initElems /** The size of the scope */ private[this] var _size = initSize - override def size = _size + override final def size = _size private def size_= (x: Int) = _size = x /** the hash table @@ -73,10 +73,10 @@ object Scopes { private var elemsCache: List[Symbol] = null /** Returns a new scope with the same content as this one. */ - def cloneScope(implicit ctx: Context): Scope = newScopeWith(this.toList: _*) + final def cloneScope(implicit ctx: Context): Scope = newScopeWith(this.toList: _*) /** is the scope empty? */ - override def isEmpty: Boolean = lastEntry eq null + override final def isEmpty: Boolean = lastEntry eq null /** create and enter a scope entry */ protected def newScopeEntry(sym: Symbol)(implicit ctx: Context): ScopeEntry = { @@ -94,7 +94,7 @@ object Scopes { e } - private def enterInHash(e: ScopeEntry)(implicit ctx: Context): Unit = { + private final def enterInHash(e: ScopeEntry)(implicit ctx: Context): Unit = { val i = e.sym.name.start & (hashTable.length - 1) e.tail = hashTable(i) hashTable(i) = e @@ -104,7 +104,7 @@ object Scopes { * * @param sym ... */ - def enter[T <: Symbol](sym: T)(implicit ctx: Context): T = { + final def enter[T <: Symbol](sym: T)(implicit ctx: Context): T = { newScopeEntry(sym) sym } @@ -113,7 +113,7 @@ object Scopes { * * @param sym ... */ - def enterUnique(sym: Symbol)(implicit ctx: Context) { + final def enterUnique(sym: Symbol)(implicit ctx: Context) { assert(lookup(sym.name) == NoSymbol, (sym.showLocated, lookup(sym.name).showLocated)) enter(sym) } @@ -146,7 +146,7 @@ object Scopes { } /** remove entry from this scope. */ - def unlink(e: ScopeEntry)(implicit ctx: Context) { + final def unlink(e: ScopeEntry)(implicit ctx: Context) { if (lastEntry == e) { lastEntry = e.prev } else { @@ -169,7 +169,7 @@ object Scopes { } /** remove symbol from this scope */ - def unlink(sym: Symbol)(implicit ctx: Context) { + final def unlink(sym: Symbol)(implicit ctx: Context) { var e = lookupEntry(sym.name) while (e ne null) { if (e.sym == sym) unlink(e); @@ -182,21 +182,21 @@ object Scopes { * @param name ... * @return ... */ - def lookup(name: Name)(implicit ctx: Context): Symbol = { + final def lookup(name: Name)(implicit ctx: Context): Symbol = { val e = lookupEntry(name) if (e eq null) NoSymbol else e.sym } /** Returns an iterator yielding every symbol with given name in this scope. */ - def lookupAll(name: Name)(implicit ctx: Context): Iterator[Symbol] = new Iterator[Symbol] { + final def lookupAll(name: Name)(implicit ctx: Context): Iterator[Symbol] = new Iterator[Symbol] { var e = lookupEntry(name) def hasNext: Boolean = e ne null def next(): Symbol = { val r = e.sym; e = lookupNextEntry(e); r } } /** The denotation set of all the symbols with given name in this scope */ - def denotsNamed(name: Name)(implicit ctx: Context): DenotationSet = { + final def denotsNamed(name: Name)(implicit ctx: Context): DenotationSet = { var syms: DenotationSet = NoDenotation var e = lookupEntry(name) while (e != null) { @@ -211,7 +211,7 @@ object Scopes { * in future versions of the type system. I have reverted the previous * change to use iterators as too costly. */ - def lookupEntry(name: Name)(implicit ctx: Context): ScopeEntry = { + final def lookupEntry(name: Name)(implicit ctx: Context): ScopeEntry = { var e: ScopeEntry = null if (hashTable ne null) { e = hashTable(name.start & (hashTable.length - 1)) @@ -228,7 +228,7 @@ object Scopes { } /** lookup next entry with same name as this one */ - def lookupNextEntry(entry: ScopeEntry)(implicit ctx: Context): ScopeEntry = { + final def lookupNextEntry(entry: ScopeEntry)(implicit ctx: Context): ScopeEntry = { var e = entry if (hashTable ne null) do { e = e.tail } while ((e ne null) && e.sym.name != entry.sym.name) @@ -239,7 +239,7 @@ object Scopes { /** Return all symbols as a list in the order they were entered in this scope. */ - override def toList: List[Symbol] = { + override final def toList: List[Symbol] = { if (elemsCache eq null) { elemsCache = Nil var e = lastEntry @@ -253,22 +253,22 @@ object Scopes { /** Vanilla scope - symbols are stored in declaration order. */ - def sorted: List[Symbol] = toList + final def sorted: List[Symbol] = toList /** Return all symbols as an iterator in the order they were entered in this scope. */ - def iterator: Iterator[Symbol] = toList.iterator + final def iterator: Iterator[Symbol] = toList.iterator - override def foreach[U](p: Symbol => U): Unit = toList foreach p + override final def foreach[U](p: Symbol => U): Unit = toList foreach p - def filteredScope(p: Symbol => Boolean)(implicit ctx: Context): Scope = { + final def filteredScope(p: Symbol => Boolean)(implicit ctx: Context): Scope = { val unfiltered = toList val filtered = unfiltered filterConserve p if (filtered eq unfiltered) this else newScopeWith(filtered: _*) } - def show(implicit ctx: Context): String = ctx.show(this) + final def show(implicit ctx: Context): String = ctx.show(this) } /** Create a new scope */ @@ -302,5 +302,5 @@ object Scopes { /** The error scope (mutable) */ - class ErrorScope(owner: Symbol) extends Scope + final class ErrorScope(owner: Symbol) extends Scope } From cbf86b8dfb378b09fdcf8e7b67b439d457861471 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Sat, 23 Feb 2013 01:55:46 +0100 Subject: [PATCH 13/22] More modifier lock down in StdNames. --- src/dotty/tools/dotc/core/StdNames.scala | 738 +++++++++++------------ 1 file changed, 369 insertions(+), 369 deletions(-) diff --git a/src/dotty/tools/dotc/core/StdNames.scala b/src/dotty/tools/dotc/core/StdNames.scala index 69f3a47450aa..f3b085254e9b 100644 --- a/src/dotty/tools/dotc/core/StdNames.scala +++ b/src/dotty/tools/dotc/core/StdNames.scala @@ -14,16 +14,16 @@ object StdNames { /** Base strings from which synthetic names are derived. */ - abstract class DefinedNames[N <: Name] { + sealed abstract class DefinedNames[N <: Name] { protected implicit def fromString(s: String): N private val kws = mutable.Set[N]() - protected def kw(name: N) = { kws += name; name } + protected final def kw(name: N) = { kws += name; name } final val keywords: collection.Set[N] = kws } - abstract class ScalaNames[N <: Name] extends DefinedNames[N] { + sealed abstract class ScalaNames[N <: Name] extends DefinedNames[N] { private def encode(s: String): N = fromString(NameTransformer.encode(s)) // Keywords, need to come first ----------------------- @@ -81,40 +81,40 @@ object StdNames { final val HASHkw: N = kw("#") final val ATkw: N = kw("@") - val ANON_CLASS: N = "$anon" - val ANON_FUN: N = "$anonfun" - val BITMAP_PREFIX: N = "bitmap$" - val BITMAP_NORMAL: N = BITMAP_PREFIX // initialization bitmap for public/protected lazy vals - val BITMAP_TRANSIENT: N = BITMAP_PREFIX + "trans$" // initialization bitmap for transient lazy vals - val BITMAP_CHECKINIT: N = BITMAP_PREFIX + "init$" // initialization bitmap for checkinit values - val BITMAP_CHECKINIT_TRANSIENT: N = BITMAP_PREFIX + "inittrans$" // initialization bitmap for transient checkinit values - val DEFAULT_GETTER: N = "$default$" - val DEFAULT_GETTER_INIT: N = encode("") - val DO_WHILE_PREFIX: N = "doWhile$" - val EMPTY: N = "" - val EMPTY_PACKAGE: N = "" - val EVIDENCE_PARAM_PREFIX: N = "evidence$" - val EXCEPTION_RESULT_PREFIX: N = "exceptionResult" - val EXPAND_SEPARATOR: N = "$$" - val IMPL_CLASS_SUFFIX: N = "$class" - val IMPORT: N = "" - val INTERPRETER_IMPORT_WRAPPER: N = "$iw" - val INTERPRETER_LINE_PREFIX: N = "line" - val INTERPRETER_VAR_PREFIX: N = "res" - val INTERPRETER_WRAPPER_SUFFIX: N = "$object" - val LOCALDUMMY_PREFIX: N = "") + final val DO_WHILE_PREFIX: N = "doWhile$" + final val EMPTY: N = "" + final val EMPTY_PACKAGE: N = "" + final val EVIDENCE_PARAM_PREFIX: N = "evidence$" + final val EXCEPTION_RESULT_PREFIX: N = "exceptionResult" + final val EXPAND_SEPARATOR: N = "$$" + final val IMPL_CLASS_SUFFIX: N = "$class" + final val IMPORT: N = "" + final val INTERPRETER_IMPORT_WRAPPER: N = "$iw" + final val INTERPRETER_LINE_PREFIX: N = "line" + final val INTERPRETER_VAR_PREFIX: N = "res" + final val INTERPRETER_WRAPPER_SUFFIX: N = "$object" + final val LOCALDUMMY_PREFIX: N = ">") - val DIV = encode("/") - val EQ = encode("==") - val EQL = encode("=") - val GE = encode(">=") - val GT = encode(">") - val HASHHASH = encode("##") - val LE = encode("<=") - val LSL = encode("<<") - val LSR = encode(">>>") - val LT = encode("<") - val MINUS = encode("-") - val MOD = encode("%") - val MUL = encode("*") - val NE = encode("!=") - val OR = encode("|") - val PLUS = ADD // technically redundant, but ADD looks funny with MINUS - val SUB = MINUS // ... as does SUB with PLUS - val XOR = encode("^") - val ZAND = encode("&&") - val ZOR = encode("||") + final val ADD = encode("+") + final val AND = encode("&") + final val ASR = encode(">>") + final val DIV = encode("/") + final val EQ = encode("==") + final val EQL = encode("=") + final val GE = encode(">=") + final val GT = encode(">") + final val HASHHASH = encode("##") + final val LE = encode("<=") + final val LSL = encode("<<") + final val LSR = encode(">>>") + final val LT = encode("<") + final val MINUS = encode("-") + final val MOD = encode("%") + final val MUL = encode("*") + final val NE = encode("!=") + final val OR = encode("|") + final val PLUS = ADD // technically redundant, but ADD looks funny with MINUS + final val SUB = MINUS // ... as does SUB with PLUS + final val XOR = encode("^") + final val ZAND = encode("&&") + final val ZOR = encode("||") // unary operators - val UNARY_~ = encode("unary_~") - val UNARY_+ = encode("unary_+") - val UNARY_- = encode("unary_-") - val UNARY_! = encode("unary_!") + final val UNARY_~ = encode("unary_~") + final val UNARY_+ = encode("unary_+") + final val UNARY_- = encode("unary_-") + final val UNARY_! = encode("unary_!") // Grouped here so Cleanup knows what tests to perform. - val CommonOpNames = Set[Name](OR, XOR, AND, EQ, NE) - val ConversionNames = Set[Name](toByte, toChar, toDouble, toFloat, toInt, toLong, toShort) - val BooleanOpNames = Set[Name](ZOR, ZAND, UNARY_!) ++ CommonOpNames - val NumberOpNames = ( + final val CommonOpNames = Set[Name](OR, XOR, AND, EQ, NE) + final val ConversionNames = Set[Name](toByte, toChar, toDouble, toFloat, toInt, toLong, toShort) + final val BooleanOpNames = Set[Name](ZOR, ZAND, UNARY_!) ++ CommonOpNames + final val NumberOpNames = ( Set[Name](ADD, SUB, MUL, DIV, MOD, LSL, LSR, ASR, LT, LE, GE, GT) ++ Set(UNARY_+, UNARY_-, UNARY_!) ++ ConversionNames ++ CommonOpNames ) - val add: N = "add" - val complement: N = "complement" - val divide: N = "divide" - val multiply: N = "multiply" - val negate: N = "negate" - val positive: N = "positive" - val shiftLogicalRight: N = "shiftLogicalRight" - val shiftSignedLeft: N = "shiftSignedLeft" - val shiftSignedRight: N = "shiftSignedRight" - val subtract: N = "subtract" - val takeAnd: N = "takeAnd" - val takeConditionalAnd: N = "takeConditionalAnd" - val takeConditionalOr: N = "takeConditionalOr" - val takeModulo: N = "takeModulo" - val takeNot: N = "takeNot" - val takeOr: N = "takeOr" - val takeXor: N = "takeXor" - val testEqual: N = "testEqual" - val testGreaterOrEqualThan: N = "testGreaterOrEqualThan" - val testGreaterThan: N = "testGreaterThan" - val testLessOrEqualThan: N = "testLessOrEqualThan" - val testLessThan: N = "testLessThan" - val testNotEqual: N = "testNotEqual" - - val isBoxedNumberOrBoolean: N = "isBoxedNumberOrBoolean" - val isBoxedNumber: N = "isBoxedNumber" - - val reflPolyCacheName: N = "reflPoly$Cache" - val reflClassCacheName: N = "reflClass$Cache" - val reflParamsCacheName: N = "reflParams$Cache" - val reflMethodCacheName: N = "reflMethod$Cache" - val reflMethodName: N = "reflMethod$Method" + final val add: N = "add" + final val complement: N = "complement" + final val divide: N = "divide" + final val multiply: N = "multiply" + final val negate: N = "negate" + final val positive: N = "positive" + final val shiftLogicalRight: N = "shiftLogicalRight" + final val shiftSignedLeft: N = "shiftSignedLeft" + final val shiftSignedRight: N = "shiftSignedRight" + final val subtract: N = "subtract" + final val takeAnd: N = "takeAnd" + final val takeConditionalAnd: N = "takeConditionalAnd" + final val takeConditionalOr: N = "takeConditionalOr" + final val takeModulo: N = "takeModulo" + final val takeNot: N = "takeNot" + final val takeOr: N = "takeOr" + final val takeXor: N = "takeXor" + final val testEqual: N = "testEqual" + final val testGreaterOrEqualThan: N = "testGreaterOrEqualThan" + final val testGreaterThan: N = "testGreaterThan" + final val testLessOrEqualThan: N = "testLessOrEqualThan" + final val testLessThan: N = "testLessThan" + final val testNotEqual: N = "testNotEqual" + + final val isBoxedNumberOrBoolean: N = "isBoxedNumberOrBoolean" + final val isBoxedNumber: N = "isBoxedNumber" + + final val reflPolyCacheName: N = "reflPoly$Cache" + final val reflClassCacheName: N = "reflClass$Cache" + final val reflParamsCacheName: N = "reflParams$Cache" + final val reflMethodCacheName: N = "reflMethod$Cache" + final val reflMethodName: N = "reflMethod$Method" private val reflectionCacheNames = Set[N]( reflPolyCacheName, @@ -592,10 +592,10 @@ object StdNames { reflMethodName ) - def isReflectionCacheName(name: Name) = reflectionCacheNames exists (name startsWith _) + final def isReflectionCacheName(name: Name) = reflectionCacheNames exists (name startsWith _) } - class ScalaTermNames extends ScalaNames[TermName] { + final class ScalaTermNames extends ScalaNames[TermName] { protected def fromString(s: String) = termName(s) @switch def syntheticParamName(i: Int): TermName = i match { @@ -619,7 +619,7 @@ object StdNames { } - class ScalaTypeNames extends ScalaNames[TypeName] { + final class ScalaTypeNames extends ScalaNames[TypeName] { protected def fromString(s: String) = typeName(s) } @@ -707,10 +707,10 @@ object StdNames { final val JavaSerializable: N = "java.io.Serializable" } - class JavaTermNames extends JavaNames[TermName] { + final class JavaTermNames extends JavaNames[TermName] { protected def fromString(s: String): TermName = termName(s) } - class JavaTypeNames extends JavaNames[TypeName] { + final class JavaTypeNames extends JavaNames[TypeName] { protected def fromString(s: String): TypeName = typeName(s) } From 63e309c6c96adc9f12de452ba431a5048f7824e7 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Sat, 23 Feb 2013 01:59:32 +0100 Subject: [PATCH 14/22] More modifier lock down in SymbolLoaders. --- src/dotty/tools/dotc/core/SymbolLoaders.scala | 58 +++++-------------- 1 file changed, 13 insertions(+), 45 deletions(-) diff --git a/src/dotty/tools/dotc/core/SymbolLoaders.scala b/src/dotty/tools/dotc/core/SymbolLoaders.scala index 2e37d8124834..3234e746eeeb 100644 --- a/src/dotty/tools/dotc/core/SymbolLoaders.scala +++ b/src/dotty/tools/dotc/core/SymbolLoaders.scala @@ -17,7 +17,7 @@ import pickling.ClassfileParser /** A base class for Symbol loaders with some overridable behavior */ class SymbolLoaders { - protected def enterIfNew(owner: Symbol, member: Symbol, completer: SymbolLoader)(implicit ctx: Context): Symbol = { + protected final def enterIfNew(owner: Symbol, member: Symbol, completer: SymbolLoader)(implicit ctx: Context): Symbol = { assert(owner.info.decls.lookup(member.name) == NoSymbol, owner.fullName + "." + member.name) owner.info.decls enter member member @@ -25,14 +25,14 @@ class SymbolLoaders { /** Enter class with given `name` into scope of `owner`. */ - def enterClass(owner: Symbol, name: PreName, completer: SymbolLoader, flags: FlagSet = EmptyFlags)(implicit ctx: Context): Symbol = { + final def enterClass(owner: Symbol, name: PreName, completer: SymbolLoader, flags: FlagSet = EmptyFlags)(implicit ctx: Context): Symbol = { val cls = ctx.newLazyClassSymbol(owner, name.toTypeName, flags, completer, assocFile = completer.sourceFileOrNull) enterIfNew(owner, cls, completer) } /** Enter module with given `name` into scope of `owner`. */ - def enterModule(owner: Symbol, name: PreName, completer: SymbolLoader, flags: FlagSet = EmptyFlags)(implicit ctx: Context): Symbol = { + final def enterModule(owner: Symbol, name: PreName, completer: SymbolLoader, flags: FlagSet = EmptyFlags)(implicit ctx: Context): Symbol = { val module = ctx.newLazyModuleSymbols(owner, name.toTermName, flags, completer, assocFile = completer.sourceFileOrNull)._1 enterIfNew(owner, module, completer) } @@ -40,7 +40,7 @@ class SymbolLoaders { /** Enter package with given `name` into scope of `owner` * and give them `completer` as type. */ - def enterPackage(owner: Symbol, name: PreName, completer: SymbolLoader)(implicit ctx: Context): Symbol = { + final def enterPackage(owner: Symbol, name: PreName, completer: SymbolLoader)(implicit ctx: Context): Symbol = { val pname = name.toTermName val preExisting = owner.info.decls lookup pname if (preExisting != NoSymbol) { @@ -69,7 +69,7 @@ class SymbolLoaders { /** Enter class and module with given `name` into scope of `owner` * and give them `completer` as type. */ - def enterClassAndModule(owner: Symbol, name: PreName, completer: SymbolLoader, flags: FlagSet = EmptyFlags)(implicit ctx: Context) { + final def enterClassAndModule(owner: Symbol, name: PreName, completer: SymbolLoader, flags: FlagSet = EmptyFlags)(implicit ctx: Context) { val clazz = enterClass(owner, name, completer, flags) val module = enterModule(owner, name, completer, flags) if (!clazz.isAnonymousClass) { @@ -84,7 +84,7 @@ class SymbolLoaders { * with source completer for given `src` as type. * (overridden in interactive.Global). */ - def enterToplevelsFromSource(owner: Symbol, name: PreName, src: AbstractFile)(implicit ctx: Context) { + final def enterToplevelsFromSource(owner: Symbol, name: PreName, src: AbstractFile)(implicit ctx: Context) { ??? // !!! enterClassAndModule(owner, name, new SourcefileLoader(src)) } @@ -95,13 +95,13 @@ class SymbolLoaders { * Note: We do a name-base comparison here because the method is called before we even * have ReflectPackage defined. */ - def binaryOnly(owner: Symbol, name: String)(implicit ctx: Context): Boolean = + final def binaryOnly(owner: Symbol, name: String)(implicit ctx: Context): Boolean = name == "package" && (owner.fullName == "scala" || owner.fullName == "scala.reflect") /** Initialize toplevel class and module symbols in `owner` from class path representation `classRep` */ - def initializeFromClassPath(owner: Symbol, classRep: ClassPath#ClassRep)(implicit ctx: Context) { + final def initializeFromClassPath(owner: Symbol, classRep: ClassPath#ClassRep)(implicit ctx: Context) { ((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) @@ -114,12 +114,12 @@ class SymbolLoaders { } } - def needCompile(bin: AbstractFile, src: AbstractFile) = + final def needCompile(bin: AbstractFile, src: AbstractFile) = src.lastModified >= bin.lastModified /** Load contents of a package */ - class PackageLoader(classpath: ClassPath)(cctx: CondensedContext) extends SymbolLoader { + final class PackageLoader(classpath: ClassPath)(cctx: CondensedContext) extends SymbolLoader { implicit val ctx: Context = cctx protected def description = "package loader " + classpath.name @@ -151,7 +151,7 @@ class SymbolLoaders { * Todo: consider factoring out behavior from TopClassCompleter/SymbolLoader into * supertrait SymLoader */ -abstract class SymbolLoader extends ClassCompleter { +sealed abstract class SymbolLoader extends ClassCompleter { implicit val ctx: Context /** Load source or class file for `root`, return */ @@ -164,7 +164,7 @@ abstract class SymbolLoader extends ClassCompleter { */ protected def description: String - override def apply(root: LazyClassDenotation) = { + override final def apply(root: LazyClassDenotation) = { def signalError(ex: Exception) { if (ctx.settings.debug.value) ex.printStackTrace() val msg = ex.getMessage() @@ -187,7 +187,7 @@ abstract class SymbolLoader extends ClassCompleter { } } -class ClassfileLoader(val classfile: AbstractFile)(cctx: CondensedContext) extends SymbolLoader { +final class ClassfileLoader(val classfile: AbstractFile)(cctx: CondensedContext) extends SymbolLoader { implicit val ctx: Context = cctx override def sourceFileOrNull: AbstractFile = classfile @@ -209,38 +209,6 @@ class ClassfileLoader(val classfile: AbstractFile)(cctx: CondensedContext) exten } } /* - class MsilFileLoader(msilFile: MsilFile) extends SymbolLoader with FlagAssigningCompleter { - private def typ = msilFile.msilType - private object typeParser extends clr.TypeParser { - val global: SymbolLoaders.this.global.type = SymbolLoaders.this.global - } - - protected def description = "MsilFile "+ typ.FullName + ", assembly "+ typ.Assembly.FullName - protected def doComplete(root: Symbol) { typeParser.parse(typ, root) } - } - - class SourcefileLoader(val srcfile: AbstractFile) extends SymbolLoader with FlagAssigningCompleter { - protected def description = "source file "+ srcfile.toString - override def fromSource = true - override def sourcefile = Some(srcfile) - protected def doComplete(root: Symbol): Unit = global.currentRun.compileLate(srcfile) - } - - object moduleClassLoader extends SymbolLoader with FlagAssigningCompleter { - protected def description = "module class loader" - protected def doComplete(root: Symbol) { root.sourceModule.initialize } - } - - object clrTypes extends clr.CLRTypes { - val global: SymbolLoaders.this.global.type = SymbolLoaders.this.global - if (global.forMSIL) init() - } - - /** used from classfile parser to avoid cyclies */ - var parentsLevel = 0 - var pendingLoadActions: List[() => Unit] = Nil -} - object SymbolLoadersStats { import scala.reflect.internal.TypesStats.typerNanos val classReadNanos = Statistics.newSubTimer ("time classfilereading", typerNanos) From d5ed6f55e76d9574ebf84c6370bca9298a1a340e Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Sat, 23 Feb 2013 02:04:02 +0100 Subject: [PATCH 15/22] More modifier lock down in Symbols. --- src/dotty/tools/dotc/core/Symbols.scala | 66 ++++++++++++------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/src/dotty/tools/dotc/core/Symbols.scala b/src/dotty/tools/dotc/core/Symbols.scala index 3615a2cca2eb..a48d753f357d 100644 --- a/src/dotty/tools/dotc/core/Symbols.scala +++ b/src/dotty/tools/dotc/core/Symbols.scala @@ -21,15 +21,15 @@ trait Symbols { this: Context => // ---- Fundamental symbol creation methods ---------------------------------- - def newLazySymbol[N <: Name](owner: Symbol, name: N, initFlags: FlagSet, completer: SymCompleter, coord: Coord = NoCoord) = + final def newLazySymbol[N <: Name](owner: Symbol, name: N, initFlags: FlagSet, completer: SymCompleter, coord: Coord = NoCoord) = new Symbol(coord, new LazySymDenotation(_, owner, name, initFlags, completer)) { type ThisName = N } - def newLazyClassSymbol(owner: Symbol, name: TypeName, initFlags: FlagSet, completer: ClassCompleter, assocFile: AbstractFile = null, coord: Coord = NoCoord) = + final def newLazyClassSymbol(owner: Symbol, name: TypeName, initFlags: FlagSet, completer: ClassCompleter, assocFile: AbstractFile = null, coord: Coord = NoCoord) = new ClassSymbol(coord, new LazyClassDenotation(_, owner, name, initFlags, completer, assocFile)(this)) - def newLazyModuleSymbols(owner: Symbol, + final def newLazyModuleSymbols(owner: Symbol, name: TermName, flags: FlagSet, completer: ClassCompleter, @@ -47,12 +47,12 @@ trait Symbols { this: Context => (module, modcls) } - def newSymbol[N <: Name](owner: Symbol, name: N, flags: FlagSet, info: Type, privateWithin: Symbol = NoSymbol, coord: Coord = NoCoord) = + final def newSymbol[N <: Name](owner: Symbol, name: N, flags: FlagSet, info: Type, privateWithin: Symbol = NoSymbol, coord: Coord = NoCoord) = new Symbol(coord, CompleteSymDenotation(_, owner, name, flags, info, privateWithin)) { type ThisName = N } - def newClassSymbol( + final def newClassSymbol( owner: Symbol, name: TypeName, flags: FlagSet, @@ -66,7 +66,7 @@ trait Symbols { this: Context => new ClassSymbol(coord, new CompleteClassDenotation( _, owner, name, flags, parents, privateWithin, optSelfType, decls, assocFile)(this)) - def newModuleSymbols( + final def newModuleSymbols( owner: Symbol, name: TermName, flags: FlagSet, @@ -89,7 +89,7 @@ trait Symbols { this: Context => (module, modcls) } - def newStubSymbol(owner: Symbol, name: Name, file: AbstractFile = null): Symbol = { + final def newStubSymbol(owner: Symbol, name: Name, file: AbstractFile = null): Symbol = { def stub = new StubCompleter(ctx.condensed) name match { case name: TermName => ctx.newLazyModuleSymbols(owner, name, EmptyFlags, stub, file)._1 @@ -99,36 +99,36 @@ trait Symbols { this: Context => // ---- Derived symbol creation methods ------------------------------------- - def newLazyPackageSymbols(owner: Symbol, name: TermName, completer: ClassCompleter) = + final def newLazyPackageSymbols(owner: Symbol, name: TermName, completer: ClassCompleter) = newLazyModuleSymbols(owner, name, PackageCreationFlags, completer) - def newPackageSymbols( + final def newPackageSymbols( owner: Symbol, name: TermName, decls: Scope = newScope) = newModuleSymbols( owner, name, PackageCreationFlags, PackageCreationFlags, Nil, NoSymbol, decls) - def newLocalDummy(cls: Symbol, coord: Coord = NoCoord) = + final def newLocalDummy(cls: Symbol, coord: Coord = NoCoord) = newSymbol(cls, nme.localDummyName(cls), EmptyFlags, NoType) - def newImportSymbol(expr: TypedTree, coord: Coord = NoCoord) = + final def newImportSymbol(expr: TypedTree, coord: Coord = NoCoord) = newSymbol(NoSymbol, nme.IMPORT, EmptyFlags, ImportType(expr), coord = coord) - def newConstructor(cls: ClassSymbol, flags: FlagSet, paramNames: List[TermName], paramTypes: List[Type], privateWithin: Symbol = NoSymbol, coord: Coord = NoCoord) = + final def newConstructor(cls: ClassSymbol, flags: FlagSet, paramNames: List[TermName], paramTypes: List[Type], privateWithin: Symbol = NoSymbol, coord: Coord = NoCoord) = newSymbol(cls, nme.CONSTRUCTOR, flags, MethodType(paramNames, paramTypes)(_ => cls.typeConstructor), privateWithin, coord) - def newDefaultConstructor(cls: ClassSymbol) = + final def newDefaultConstructor(cls: ClassSymbol) = newConstructor(cls, EmptyFlags, Nil, Nil) - def newSelfSym(cls: ClassSymbol) = + final def newSelfSym(cls: ClassSymbol) = ctx.newSymbol(cls, nme.THIS, SyntheticArtifact, cls.selfType) /** Create new type parameters with given owner, names, and flags. * @param boundsFn A function that, given type refs to the newly created * parameters returns a list of their bounds. */ - def newTypeParams( + final def newTypeParams( owner: Symbol, names: List[TypeName], flags: FlagSet, @@ -146,13 +146,13 @@ trait Symbols { this: Context => // ----- Locating predefined symbols ---------------------------------------- - def requiredPackage(path: PreName): TermSymbol = + final def requiredPackage(path: PreName): TermSymbol = base.staticRef(path.toTermName).requiredSymbol(_.isPackage).asTerm - def requiredClass(path: PreName): ClassSymbol = + final def requiredClass(path: PreName): ClassSymbol = base.staticRef(path.toTypeName).requiredSymbol(_.isClass).asClass - def requiredModule(path: PreName): TermSymbol = + final def requiredModule(path: PreName): TermSymbol = base.staticRef(path.toTermName).requiredSymbol(_.isModule).asTerm } @@ -160,7 +160,7 @@ object Symbols { /** A Symbol represents a Scala definition/declaration or a package. */ - class Symbol(val coord: Coord, denotf: Symbol => SymDenotation) extends DotClass { + sealed class Symbol(val coord: Coord, denotf: Symbol => SymDenotation) extends DotClass { type ThisName <: Name @@ -168,15 +168,15 @@ object Symbols { def exists = true /** This symbol, if it exists, otherwise the result of evaluating `that` */ - def orElse(that: => Symbol) = if (exists) this else that + final def orElse(that: => Symbol) = if (exists) this else that /** If this symbol satisfies predicate `p` this symbol, otherwise `NoSymbol` */ - def filter(p: Symbol => Boolean): Symbol = if (p(this)) this else NoSymbol + final def filter(p: Symbol => Boolean): Symbol = if (p(this)) this else NoSymbol private[this] var _id: Int = _ /** The unique id of this symbol */ - def id(implicit ctx: Context) = { + final def id(implicit ctx: Context) = { if (_id == 0) _id = ctx.nextId _id } @@ -215,31 +215,31 @@ object Symbols { } /** Is symbol a primitive value class? */ - def isPrimitiveValueClass(implicit ctx: Context) = defn.ScalaValueClasses contains this + final def isPrimitiveValueClass(implicit ctx: Context) = defn.ScalaValueClasses contains this /** Is symbol a phantom class for which no runtime representation exists? */ - def isPhantomClass(implicit ctx: Context) = defn.PhantomClasses contains this + final def isPhantomClass(implicit ctx: Context) = defn.PhantomClasses contains this /** The current name of this symbol */ final def name(implicit ctx: Context): ThisName = denot.name.asInstanceOf[ThisName] - def show(implicit ctx: Context): String = ctx.show(this) - def showLocated(implicit ctx: Context): String = ctx.showLocated(this) - def showDcl(implicit ctx: Context): String = ctx.showDcl(this) - def showKind(implicit ctx: Context): String = ctx.showKind(this) - def showName(implicit ctx: Context): String = ctx.showName(this) - def showFullName(implicit ctx: Context): String = ctx.showFullName(this) + final def show(implicit ctx: Context): String = ctx.show(this) + final def showLocated(implicit ctx: Context): String = ctx.showLocated(this) + final def showDcl(implicit ctx: Context): String = ctx.showDcl(this) + final def showKind(implicit ctx: Context): String = ctx.showKind(this) + final def showName(implicit ctx: Context): String = ctx.showName(this) + final def showFullName(implicit ctx: Context): String = ctx.showFullName(this) } type TermSymbol = Symbol { type ThisName = TermName } type TypeSymbol = Symbol { type ThisName = TypeName } - class ClassSymbol(coord: Coord, denotf: ClassSymbol => ClassDenotation) extends Symbol(coord, s => denotf(s.asClass)) { + final class ClassSymbol(coord: Coord, denotf: ClassSymbol => ClassDenotation) extends Symbol(coord, s => denotf(s.asClass)) { type ThisName = TypeName - final def classDenot(implicit ctx: Context): ClassDenotation = + def classDenot(implicit ctx: Context): ClassDenotation = denot.asInstanceOf[ClassDenotation] private var superIdHint: Int = -1 @@ -265,7 +265,7 @@ object Symbols { } } - class ErrorSymbol(val underlying: Symbol, msg: => String)(implicit ctx: Context) extends Symbol(NoCoord, sym => underlying.denot) { + final class ErrorSymbol(val underlying: Symbol, msg: => String)(implicit ctx: Context) extends Symbol(NoCoord, sym => underlying.denot) { type ThisName = underlying.ThisName } From a0e343a8c2e435759e44a191ce88b57085919981 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Sat, 23 Feb 2013 02:17:24 +0100 Subject: [PATCH 16/22] modifier lock down in SymDenotations / populate _typeParams cache --- .../tools/dotc/core/SymDenotations.scala | 151 +++++++++--------- src/dotty/tools/dotc/core/SymbolLoaders.scala | 2 +- 2 files changed, 78 insertions(+), 75 deletions(-) diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala index 2bafb77328db..f35e5bb2081d 100644 --- a/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/src/dotty/tools/dotc/core/SymDenotations.scala @@ -16,7 +16,7 @@ object SymDenotations { /** A denotation represents the contents of a definition * during a period. */ - abstract class SymDenotation(initFlags: FlagSet) extends SingleDenotation { + sealed abstract class SymDenotation(initFlags: FlagSet) extends SingleDenotation { // ----- denotation fields and accessors ------------------------------ @@ -40,7 +40,7 @@ object SymDenotations { def info: Type /** The name with which the denoting symbol was created */ - def originalName = + final def originalName = if (flags is ExpandedName) initial.asSymDenotation.name else name /** The encoded full path name of this denotation, where outer names and inner names @@ -64,38 +64,38 @@ object SymDenotations { /** The source file from which this denotation was generated, null if not applicable. */ final def sourceFile(implicit ctx: Context): AbstractFile = pickFile(associatedFile, classFile = false) - /** Desire to re-use the field in ClassSymbol which stores the source - * file to also store the classfile, but without changing the behavior - * of sourceFile (which is expected at least in the IDE only to - * return actual source code.) So sourceFile has classfiles filtered out. - */ + /** Desire to re-use the field in ClassSymbol which stores the source + * file to also store the classfile, but without changing the behavior + * of sourceFile (which is expected at least in the IDE only to + * return actual source code.) So sourceFile has classfiles filtered out. + */ private def pickFile(file: AbstractFile, classFile: Boolean): AbstractFile = if ((file eq null) || classFile != (file.path endsWith ".class")) null else file private[this] var _flags: FlagSet = initFlags /** The flag set */ - def flags: FlagSet = { ensureCompleted(); _flags } + final def flags: FlagSet = { ensureCompleted(); _flags } /** Update the flag set */ - private[core] def flags_=(flags: FlagSet): Unit = { _flags = flags } + private[core] final def flags_=(flags: FlagSet): Unit = { _flags = flags } /** Set given flags(s) of this denotation */ - def setFlag(flags: FlagSet): Unit = { _flags |= flags } + final def setFlag(flags: FlagSet): Unit = { _flags |= flags } /** UnsSet given flags(s) of this denotation */ - def resetFlag(flags: FlagSet): Unit = { _flags &~= flags } + final def resetFlag(flags: FlagSet): Unit = { _flags &~= flags } private[this] var _annotations: List[Annotation] = Nil /** The annotations of this denotation */ - def annotations: List[Annotation] = { ensureCompleted(); _annotations } + final def annotations: List[Annotation] = { ensureCompleted(); _annotations } /** Update the annotations of this denotation */ - private[core] def annotations_=(annots: List[Annotation]): Unit = { _annotations = annots } + private[core] final def annotations_=(annots: List[Annotation]): Unit = { _annotations = annots } /** Does this denotation have an annotation matching the given class symbol? */ - def hasAnnotation(cls: Symbol)(implicit ctx: Context) = dropOtherAnnotations(annotations, cls).nonEmpty + final def hasAnnotation(cls: Symbol)(implicit ctx: Context) = dropOtherAnnotations(annotations, cls).nonEmpty /** Add given annotation to the annotations of this denotation */ final def addAnnotation(annot: Annotation): Unit = annotations = @@ -155,19 +155,19 @@ object SymDenotations { def exists(implicit ctx: Context) = true /** Is this symbol the root class or its companion object? */ - def isRoot: Boolean = name.toTermName == nme.ROOT + final def isRoot: Boolean = name.toTermName == nme.ROOT /** Is this symbol the empty package class or its companion object? */ - def isEmptyPackage(implicit ctx: Context): Boolean = name.toTermName == nme.EMPTY_PACKAGE && owner.isRoot + final def isEmptyPackage(implicit ctx: Context): Boolean = name.toTermName == nme.EMPTY_PACKAGE && owner.isRoot /** Is this symbol the empty package class or its companion object? */ - def isEffectiveRoot(implicit ctx: Context) = isRoot || isEmptyPackage + final def isEffectiveRoot(implicit ctx: Context) = isRoot || isEmptyPackage /** Is this symbol an anonymous class? */ - def isAnonymousClass(implicit ctx: Context): Boolean = initial.asSymDenotation.name startsWith tpnme.ANON_CLASS + final def isAnonymousClass(implicit ctx: Context): Boolean = initial.asSymDenotation.name startsWith tpnme.ANON_CLASS /** Is this symbol an abstract type? */ - def isAbstractType = isType && info.isRealTypeBounds + final def isAbstractType = isType && info.isRealTypeBounds /** Is this definition contained in `boundary`? * Same as `ownersIterator contains boundary` but more efficient. @@ -182,14 +182,14 @@ object SymDenotations { } /** Is this denotation static (i.e. with no outer instance)? */ - def isStatic(implicit ctx: Context) = (this is Static) || owner.isStaticOwner + final def isStatic(implicit ctx: Context) = (this is Static) || owner.isStaticOwner /** Is this a package class or module class that defines static symbols? */ final def isStaticOwner(implicit ctx: Context): Boolean = isPackageClass || isModuleClass && isStatic /** Is this denotation defined in the same scope and compilation unit as that symbol? */ - def isCoDefinedWith(that: Symbol)(implicit ctx: Context) = + final def isCoDefinedWith(that: Symbol)(implicit ctx: Context) = (this.effectiveOwner == that.effectiveOwner) && ( !(this.effectiveOwner.isPackageClass) || (this.sourceFile == null) @@ -210,29 +210,29 @@ object SymDenotations { def isSubClass(base: Symbol)(implicit ctx: Context) = false /** Is this a user defined "def" method? Excluded are accessors and stable values */ - def isSourceMethod = this is (Method, butNot = Accessor) + final def isSourceMethod = this is (Method, butNot = Accessor) /** Is this NOT a user-defined "def" method that takes parameters? */ - def isParameterless(implicit ctx: Context) = + final def isParameterless(implicit ctx: Context) = !isSourceMethod || info.paramTypess.isEmpty /** Is this a setter? */ - def isGetter = (this is Accessor) && !originalName.isSetterName + final def isGetter = (this is Accessor) && !originalName.isSetterName /** Is this a setter? */ - def isSetter = (this is Accessor) && originalName.isSetterName + final def isSetter = (this is Accessor) && originalName.isSetterName /** is this the constructor of a class? */ - def isClassConstructor = name == nme.CONSTRUCTOR + final def isClassConstructor = name == nme.CONSTRUCTOR /** Is this the constructor of a trait? */ - def isTraitConstructor = name == nme.TRAIT_CONSTRUCTOR + final def isTraitConstructor = name == nme.TRAIT_CONSTRUCTOR /** Is this the constructor of a trait or a class */ - def isConstructor = name.isConstructorName + final def isConstructor = name.isConstructorName /** Is this a local template dummmy? */ - def isLocalDummy: Boolean = name.isLocalDummyName + final def isLocalDummy: Boolean = name.isLocalDummyName /** Does this symbol denote the primary constructor of its enclosing class? */ final def isPrimaryConstructor(implicit ctx: Context) = @@ -249,13 +249,13 @@ object SymDenotations { isModuleClass && linkedClass.isNonBottomSubClass(base) /** Is this symbol a class that does not extend `AnyVal`? */ - def isNonValueClass(implicit ctx: Context): Boolean = + final def isNonValueClass(implicit ctx: Context): Boolean = isClass && !isSubClass(defn.AnyValClass) /** Is this definition accessible whenever `that` symbol is accessible? * Does not take into account status of protected members. */ - def isAsAccessibleAs(that: Symbol)(implicit ctx: Context): Boolean = + final def isAsAccessibleAs(that: Symbol)(implicit ctx: Context): Boolean = (that.accessBoundary(NoSymbol) isContainedIn this.accessBoundary(NoSymbol)) && (this.isStable || !that.isStable) @@ -263,7 +263,7 @@ object SymDenotations { * @param pre The type of the tree from which the selection is made * @param superAccess Access is via super */ - def isAccessibleFrom(pre: Type, superAccess: Boolean = false)(implicit ctx: Context): Boolean = { + final def isAccessibleFrom(pre: Type, superAccess: Boolean = false)(implicit ctx: Context): Boolean = { def accessWithinLinked(boundary: Symbol) = { val linked = boundary.linkedClass @@ -362,7 +362,7 @@ object SymDenotations { /** The class containing this denotation. * If this denotation is already a class, return itself */ - def enclosingClass(implicit ctx: Context): Symbol = + final def enclosingClass(implicit ctx: Context): Symbol = if (isClass) symbol else owner.enclosingClass /** The top-level class containing this denotation, @@ -381,7 +381,7 @@ object SymDenotations { * and which is also defined in the same scope and compilation unit. * NoSymbol if this module does not exist. */ - def companionModule(implicit ctx: Context): Symbol = { + final def companionModule(implicit ctx: Context): Symbol = { owner.info.decl(name.toTermName) .suchThat(sym => sym.isModule && sym.isCoDefinedWith(symbol)) .symbol @@ -391,7 +391,7 @@ object SymDenotations { * and which is also defined in the same scope and compilation unit. * NoSymbol if this class does not exist. */ - def companionClass(implicit ctx: Context): Symbol = + final def companionClass(implicit ctx: Context): Symbol = owner.info.decl(name.toTypeName) .suchThat(sym => sym.isClass && sym.isCoDefinedWith(symbol)) .symbol @@ -400,7 +400,7 @@ object SymDenotations { * If this is a module class, its companion class. * NoSymbol otherwise. */ - def linkedClass(implicit ctx: Context): Symbol = + final def linkedClass(implicit ctx: Context): Symbol = if (this.isModuleClass) companionClass else if (this.isClass) companionModule.moduleClass else NoSymbol @@ -475,23 +475,23 @@ object SymDenotations { /** The symbolic typeref representing the type constructor for this type. * @throws ClassCastException is this is not a type */ - def symbolicRef(implicit ctx: Context): TypeRef = + final def symbolicRef(implicit ctx: Context): TypeRef = TypeRef(owner.thisType, symbol.asType) /** The variance of this type parameter as an Int, with * +1 = Covariant, -1 = Contravariant, 0 = Nonvariant, or not a type parameter */ - def variance: Int = + final def variance: Int = if (this is Covariant) 1 else if (this is Contravariant) -1 else 0 // ----- copies ------------------------------------------------------ - override protected def newLikeThis(s: Symbol, i: Type): SingleDenotation = new UniqueRefDenotation(s, i, validFor) + override protected final def newLikeThis(s: Symbol, i: Type): SingleDenotation = new UniqueRefDenotation(s, i, validFor) /** Copy this denotation, overriding selective fields */ - def copy( + final def copy( sym: Symbol, owner: Symbol = this.owner, name: Name = this.name, @@ -505,7 +505,7 @@ object SymDenotations { * Note: important to leave initctx non-implicit, and to check that it is not * retained after object construction. */ - abstract class ClassDenotation(initFlags: FlagSet, assocFile: AbstractFile)(initctx: Context) + sealed abstract class ClassDenotation(initFlags: FlagSet, assocFile: AbstractFile)(initctx: Context) extends SymDenotation(initFlags) { import NameFilter._ import util.LRU8Cache @@ -527,33 +527,36 @@ object SymDenotations { def name: TypeName - override val info = { + override final val info = { implicit val ctx = initctx ClassInfo(owner.thisType, this) } - override def associatedFile(implicit ctx: Context): AbstractFile = assocFile + override final def associatedFile(implicit ctx: Context): AbstractFile = assocFile private[this] var _typeParams: List[TypeSymbol] = _ /** The type parameters of this class */ override final def typeParams(implicit ctx: Context): List[TypeSymbol] = { val tparams = _typeParams - if (tparams != null) tparams else computeTypeParams + if (tparams != null) tparams else { + _typeParams = computeTypeParams + _typeParams + } } /** The symbols defined in this class when the class is not yet completed. */ protected def preCompleteDecls: Scope - private def computeTypeParams(implicit ctx: Context): List[TypeSymbol] = + private final def computeTypeParams(implicit ctx: Context): List[TypeSymbol] = (preCompleteDecls.toList filter (_ is TypeParam)).asInstanceOf[List[TypeSymbol]] // ------ class-specific operations ----------------------------------- private[this] var _thisType: Type = null - override def thisType(implicit ctx: Context): Type = { + override final def thisType(implicit ctx: Context): Type = { if (_thisType == null) _thisType = computeThisType _thisType } @@ -611,7 +614,7 @@ object SymDenotations { /** The base classes of this class in linearization order, * with the class itself as first element. */ - def baseClasses(implicit ctx: Context): List[ClassSymbol] = { + final def baseClasses(implicit ctx: Context): List[ClassSymbol] = { if (_baseClasses == null) computeSuperClassBits _baseClasses } @@ -629,7 +632,7 @@ object SymDenotations { private[this] var _definedFingerPrint: FingerPrint = null private def computeDefinedFingerPrint(implicit ctx: Context): FingerPrint = { - var bits = newNameFilter + val bits = newNameFilter var e = decls.lastEntry while (e != null) { includeName(bits, name) @@ -660,7 +663,7 @@ object SymDenotations { * Note: We require that this does not happen after the first time * someone does a findMember on a subclass. */ - def enter(sym: Symbol)(implicit ctx: Context) = { + final def enter(sym: Symbol)(implicit ctx: Context) = { require(!(this is Frozen)) decls enter sym if (_definedFingerPrint != null) @@ -673,7 +676,7 @@ object SymDenotations { * Note: We require that this does not happen after the first time * someone does a findMember on a subclass. */ - def delete(sym: Symbol)(implicit ctx: Context) = { + final def delete(sym: Symbol)(implicit ctx: Context) = { require(!(this is Frozen)) decls unlink sym if (_definedFingerPrint != null) @@ -682,7 +685,7 @@ object SymDenotations { memberCache invalidate sym.name } - def definedFingerPrint(implicit ctx: Context): FingerPrint = { + final def definedFingerPrint(implicit ctx: Context): FingerPrint = { val fp = _definedFingerPrint if (fp != null) fp else computeDefinedFingerPrint } @@ -758,7 +761,7 @@ object SymDenotations { private[this] var memberNamesCache: Map[NameFilter, Set[Name]] = Map() - def memberNames(keepOnly: NameFilter)(implicit ctx: Context): Set[Name] = + final def memberNames(keepOnly: NameFilter)(implicit ctx: Context): Set[Name] = memberNamesCache get keepOnly match { case Some(names) => names @@ -784,15 +787,15 @@ object SymDenotations { } // to avoid overloading ambiguities - override def fullName(implicit ctx: Context): Name = super.fullName + override final def fullName(implicit ctx: Context): Name = super.fullName - override def primaryConstructor(implicit ctx: Context): Symbol = { + override final def primaryConstructor(implicit ctx: Context): Symbol = { val cname = if (this is Trait | ImplClass) nme.TRAIT_CONSTRUCTOR else nme.CONSTRUCTOR decls.denotsNamed(cname).first.symbol } - def copyClass( + final def copyClass( sym: ClassSymbol, owner: Symbol = this.owner, name: TypeName = this.name, @@ -807,7 +810,7 @@ object SymDenotations { // -------- Concrete classes for instantiating denotations -------------------------- - class CompleteSymDenotation( + final class CompleteSymDenotation( val symbol: Symbol, val owner: Symbol, val name: Name, @@ -816,11 +819,11 @@ object SymDenotations { val privateWithin: Symbol ) extends SymDenotation(initFlags) - def CompleteSymDenotation(symbol: Symbol, owner: Symbol, name: Name, initFlags: FlagSet, + def CompleteSymDenotation(symbol: Symbol, owner: Symbol, name: Name, initFlags: FlagSet, info: Type, privateWithin: Symbol = NoSymbol) = new CompleteSymDenotation(symbol, owner, name, initFlags, info, privateWithin) - class LazySymDenotation( + final class LazySymDenotation( val symbol: Symbol, val owner: Symbol, val name: Name, @@ -828,7 +831,7 @@ object SymDenotations { var completer: SymCompleter ) extends SymDenotation(initFlags) with isLazy[LazySymDenotation] { - final override def exists(implicit ctx: Context) = + override def exists(implicit ctx: Context) = !isModuleVal || moduleClass.denot.exists private[this] var _info: Type = _ @@ -840,7 +843,7 @@ object SymDenotations { completer: SymCompleter) = new LazySymDenotation(symbol, owner, name, initFlags, completer) - class CompleteClassDenotation( + final class CompleteClassDenotation( val symbol: ClassSymbol, val owner: Symbol, val name: TypeName, @@ -855,7 +858,7 @@ object SymDenotations { final def preCompleteDecls = decls } - def CompleteClassDenotation( + def CompleteClassDenotation( symbol: ClassSymbol, owner: Symbol, name: TypeName, initFlags: FlagSet, parents: List[TypeRef], privateWithin: Symbol = NoSymbol, optSelfType: Type = NoType, @@ -864,7 +867,7 @@ object SymDenotations { new CompleteClassDenotation(symbol, owner, name, initFlags, parents, privateWithin, optSelfType, decls, assocFile)(ctx) - class LazyClassDenotation( + final class LazyClassDenotation( val symbol: ClassSymbol, val owner: Symbol, val name: TypeName, @@ -881,13 +884,13 @@ object SymDenotations { protected[core] def selfType_=(tp: Type) = if (_selfType == null) _selfType = tp protected[core] def decls_=(sc: Scope) = if (_decls == null) _decls = sc - final def parents: List[TypeRef] = { if (_parents == null) tryComplete(); _parents } + def parents: List[TypeRef] = { if (_parents == null) tryComplete(); _parents } def selfType: Type = { if (_selfType == null) tryComplete(); _selfType } - final def preCompleteDecls = { if (_decls == null) tryComplete(); _decls } - final def decls: Scope = { ensureCompleted(); _decls } + def preCompleteDecls = { if (_decls == null) tryComplete(); _decls } + def decls: Scope = { ensureCompleted(); _decls } // cannot check on decls because decls might be != null even if class is not completed - final override def exists(implicit ctx: Context) = { ensureCompleted(); _parents != null } + override def exists(implicit ctx: Context) = { ensureCompleted(); _parents != null } } def LazyClassDenotation( @@ -908,14 +911,14 @@ object SymDenotations { // ---- Completion -------------------------------------------------------- - trait isLazy[Denot <: SymDenotation] extends SymDenotation { this: Denot => + sealed trait isLazy[Denot <: SymDenotation] extends SymDenotation { this: Denot => protected def completer: Completer[Denot] protected def completer_= (c: Completer[Denot]) - override def isCompleted = completer == null + override final def isCompleted = completer == null - override protected[core] def tryComplete(): Unit = + override protected[core] final def tryComplete(): Unit = try { if (flags is Locked) throw new CyclicReference(symbol) setFlag(Locked) @@ -929,8 +932,8 @@ object SymDenotations { } private[this] var _privateWithin: Symbol = _ - def privateWithin: Symbol = { if (_privateWithin == null) tryComplete(); _privateWithin } - protected[core] def privateWithin_=(sym: Symbol): Unit = { _privateWithin = sym } + final def privateWithin: Symbol = { if (_privateWithin == null) tryComplete(); _privateWithin } + protected[core] final def privateWithin_=(sym: Symbol): Unit = { _privateWithin = sym } } /** When called, complete denotation, setting all its properties */ @@ -938,7 +941,7 @@ object SymDenotations { type SymCompleter = Completer[LazySymDenotation] type ClassCompleter = Completer[LazyClassDenotation] - class ModuleCompleter(cctx: CondensedContext) extends SymCompleter { + final class ModuleCompleter(cctx: CondensedContext) extends SymCompleter { implicit protected def ctx: Context = cctx def apply(denot: LazySymDenotation): Unit = { val from = denot.moduleClass.denot.asInstanceOf[LazyClassDenotation] @@ -949,7 +952,7 @@ object SymDenotations { } /** A completer for missing references */ - class StubCompleter(cctx: CondensedContext) extends ClassCompleter { + final class StubCompleter(cctx: CondensedContext) extends ClassCompleter { implicit protected def ctx: Context = cctx def initializeToDefaults(denot: LazyClassDenotation) = { @@ -976,7 +979,7 @@ object SymDenotations { } } - class CompletionError(denot: SymDenotation) extends Error("Trying to access missing symbol ${denot.symbol.fullName}") + final class CompletionError(denot: SymDenotation) extends Error("Trying to access missing symbol ${denot.symbol.fullName}") // ---- Name filter -------------------------------------------------------- diff --git a/src/dotty/tools/dotc/core/SymbolLoaders.scala b/src/dotty/tools/dotc/core/SymbolLoaders.scala index 3234e746eeeb..1b5a3f531f91 100644 --- a/src/dotty/tools/dotc/core/SymbolLoaders.scala +++ b/src/dotty/tools/dotc/core/SymbolLoaders.scala @@ -180,7 +180,7 @@ sealed abstract class SymbolLoader extends ClassCompleter { case ex: IOException => signalError(ex) } finally { - root.linkedClass.denot match { + (root.linkedClass.denot : @unchecked) match { // TODO JZ really only one case here? case companion: LazyClassDenotation => companion.completer = null } } From 93d736b277e6db23cb4803bcd5eb39789b311440 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Sat, 23 Feb 2013 02:37:53 +0100 Subject: [PATCH 17/22] More modifier lock down in Trees. This commit exposes a number of inexhaustive matches: [warn] /Users/jason/code/dotty/src/dotty/tools/dotc/core/Trees.scala:716: match may not be exhaustive. [warn] It would fail on the following inputs: Function(_, _), GenericApply(), ModuleDef(_, _, _), TypedSplice() [warn] def transform(tree: Tree[T], c: C): Tree[T] = tree match { [warn] ^ [warn] /Users/jason/code/dotty/src/dotty/tools/dotc/core/Trees.scala:870: match may not be exhaustive. [warn] It would fail on the following inputs: Function(_, _), GenericApply(), ModuleDef(_, _, _), TypedSplice() [warn] def foldOver(x: T, tree: Tree[U]): T = tree match { [warn] ^ [warn] two warnings found [info] Compiling 52 Scala sources to /Users/jason/code/dotty/target/scala-2.10/classes... [warn] /Users/jason/code/dotty/src/dotty/tools/dotc/core/PluggableTransformers.scala:80: match may not be exhaustive. [warn] It would fail on the following inputs: Alternative(_), AndTypeTree(_, _), Annotated(_, _), AppliedTypeTree(_, _), Assign(_, _), Bind(_, _), Block(_, _), CaseDef(_, _, _), ClassDef(_, _, _, _), DefDef(_, _, _, _, _, _), EmptyTree(), EmptyValDef(), Function(_, _), GenericApply(), If(_, _, _), Import(_, _), Literal(_), Match(_, _), ModuleDef(_, _, _), NamedArg(_, _), New(_), OrTypeTree(_, _), PackageDef(_, _), Pair(_, _), RefineTypeTree(_, _), Return(_, _), SelectFromTypeTree(_, _), SeqLiteral(_, _), Shared(_), SingletonTypeTree(_), Super(_, _), Template(_, _, _), This(_), Throw(_), Tree(), Try(_, _, _), TypeBoundsTree(_, _), TypeDef(_, _, _), TypeTree(_), Typed(_, _), TypedSplice(), UnApply(_, _) [warn] protected def postProcess(tree: Tree[T], old: Tree[T], c: Context, plugins: Plugins): Tree[T] = tree match { [warn] ^ [warn] /Users/jason/code/dotty/src/dotty/tools/dotc/core/Trees.scala:716: match may not be exhaustive. [warn] It would fail on the following inputs: Function(_, _), GenericApply(), ModuleDef(_, _, _), TypedSplice() [warn] def transform(tree: Tree[T], c: C): Tree[T] = tree match { [warn] ^ [warn] /Users/jason/code/dotty/src/dotty/tools/dotc/core/Trees.scala:870: match may not be exhaustive. [warn] It would fail on the following inputs: Function(_, _), GenericApply(), ModuleDef(_, _, _), TypedSplice() [warn] def foldOver(x: T, tree: Tree[U]): T = tree match { [warn] ^ [warn] /Users/jason/code/dotty/src/dotty/tools/dotc/core/TypedTrees.scala:359: match may not be exhaustive. [warn] It would fail on the following inputs: EmptyTree(), GenericApply(), Try(_, _, _) [warn] def checkType(tree: tpd.Tree)(implicit ctx: Context): Unit = tree match { [warn] --- src/dotty/tools/dotc/core/Trees.scala | 44 +++++++++++++-------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/dotty/tools/dotc/core/Trees.scala b/src/dotty/tools/dotc/core/Trees.scala index 384a44ef42c7..284e1b6a4d13 100644 --- a/src/dotty/tools/dotc/core/Trees.scala +++ b/src/dotty/tools/dotc/core/Trees.scala @@ -30,7 +30,7 @@ object Trees { * - Type checking an untyped tree will remove all embedded `TypedSplice` * nodes. */ - abstract class Tree[T] extends DotClass { + sealed abstract class Tree[T] extends DotClass { /** The tree's position. Except * for Shared nodes, it is always ensured that a tree's position @@ -54,7 +54,7 @@ object Trees { /** Copy `tpe` attribute from tree `from` into this tree, independently * whether it is null or not. */ - def copyAttr(from: Tree[T]): ThisTree[T] = { + final def copyAttr(from: Tree[T]): ThisTree[T] = { _tpe = from._tpe this.asInstanceOf[ThisTree[T]] } @@ -92,11 +92,11 @@ object Trees { /** Is this tree either the empty tree or the empty ValDef? */ def isEmpty: Boolean = false - override def hashCode(): Int = System.identityHashCode(this) - override def equals(that: Any) = this eq that.asInstanceOf[AnyRef] + override final def hashCode(): Int = System.identityHashCode(this) + override final def equals(that: Any) = this eq that.asInstanceOf[AnyRef] } - class UnAssignedTypeException[T](tree: Tree[T]) extends RuntimeException { + final class UnAssignedTypeException[T](tree: Tree[T]) extends RuntimeException { override def getMessage: String = s"type of $tree is not assigned" } @@ -108,7 +108,7 @@ object Trees { /** Instances of this class are trees for which isType is definitely true. * Note that some trees have isType = true without being TypTrees (e.g. Ident, AnnotatedTree) */ - trait TypTree[T] extends Tree[T] { + sealed trait TypTree[T] extends Tree[T] { type ThisTree[T] <: TypTree[T] override def isType = true } @@ -116,7 +116,7 @@ object Trees { /** Instances of this class are trees for which isTerm is definitely true. * Note that some trees have isTerm = true without being TermTrees (e.g. Ident, AnnotatedTree) */ - trait TermTree[T] extends Tree[T] { + sealed trait TermTree[T] extends Tree[T] { type ThisTree[T] <: TermTree[T] override def isTerm = true } @@ -124,19 +124,19 @@ object Trees { /** Instances of this class are trees which are not terms but are legal * parts of patterns. */ - trait PatternTree[T] extends Tree[T] { + sealed trait PatternTree[T] extends Tree[T] { type ThisTree[T] <: PatternTree[T] override def isPattern = true } /** Tree's symbol can be derived from its type */ - abstract class SymTree[T] extends Tree[T] { + sealed abstract class SymTree[T] extends Tree[T] { type ThisTree[T] <: SymTree[T] - override def denot(implicit ctx: Context) = tpe match { + override final def denot(implicit ctx: Context) = tpe match { case tpe: NamedType => tpe.denot case _ => NoDenotation } - override def symbol(implicit ctx: Context): Symbol = tpe match { + override final def symbol(implicit ctx: Context): Symbol = tpe match { case tpe: Type => if (isType) tpe.typeSymbol else tpe.termSymbol case _ => NoSymbol } @@ -145,23 +145,23 @@ object Trees { /** Tree's symbol/isType/isTerm properties come from a subtree identified * by `forwardTo`. */ - abstract class ProxyTree[T] extends Tree[T] { + sealed abstract class ProxyTree[T] extends Tree[T] { type ThisTree[T] <: ProxyTree[T] def forwardTo: Tree[T] - override def denot(implicit ctx: Context): Denotation = forwardTo.denot - override def symbol(implicit ctx: Context): Symbol = forwardTo.symbol + override final def denot(implicit ctx: Context): Denotation = forwardTo.denot + override final def symbol(implicit ctx: Context): Symbol = forwardTo.symbol override def isTerm = forwardTo.isTerm override def isType = forwardTo.isType } /** Tree has a name */ - abstract class NameTree[T] extends SymTree[T] { + sealed abstract class NameTree[T] extends SymTree[T] { type ThisTree[T] <: NameTree[T] def name: Name } /** Tree refers by name to a denotation */ - abstract class RefTree[T] extends NameTree[T] { + sealed abstract class RefTree[T] extends NameTree[T] { type ThisTree[T] <: RefTree[T] def qualifier: Tree[T] override def isType = name.isTypeName @@ -169,9 +169,9 @@ object Trees { } /** Tree represents a definition */ - abstract class DefTree[T] extends NameTree[T] { + sealed abstract class DefTree[T] extends NameTree[T] { type ThisTree[T] <: DefTree[T] - override def isDef = true + override final def isDef = true } // ----------- Tree case classes ------------------------------------ @@ -477,7 +477,7 @@ object Trees { def forwardTo = arg } - trait AlwaysEmpty[T] extends Tree[T] { + sealed trait AlwaysEmpty[T] extends Tree[T] { override val pos = NoPosition override def tpe = unsupported("tpe") override def withType(tpe: Type) = unsupported("withType") @@ -519,7 +519,7 @@ object Trees { // ----- Tree cases that exist in untyped form only ------------------ /** A typed subtree of an untyped tree needs to be wrapped in a TypedSlice */ - class TypedSplice(tree: TypedTree) extends UntypedTree { + final class TypedSplice(tree: TypedTree) extends UntypedTree { val pos = tree.pos } @@ -707,7 +707,7 @@ object Trees { } abstract class TreeTransformer[T, C] { - var sharedMemo: Map[Shared[T], Shared[T]] = Map() + final var sharedMemo: Map[Shared[T], Shared[T]] = Map() def transform(tree: Tree[T], c: C): Tree[T] = tree match { case Ident(name) => @@ -856,7 +856,7 @@ object Trees { } abstract class TreeAccumulator[T, U] extends ((T, Tree[U]) => T) { - var sharedMemo: Map[Shared[U], T] = Map() + final var sharedMemo: Map[Shared[U], T] = Map() def apply(x: T, tree: Tree[U]): T def apply(x: T, trees: List[Tree[U]]): T = (x /: trees)(apply) def foldOver(x: T, tree: Tree[U]): T = tree match { From ce42e926e86b7d919b4db0271f3b4ec4b1b20341 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Sat, 23 Feb 2013 02:40:36 +0100 Subject: [PATCH 18/22] More modifier lock down in Type{Comparers, Ops} --- src/dotty/tools/dotc/core/TypeComparers.scala | 2 +- src/dotty/tools/dotc/core/TypeOps.scala | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/dotty/tools/dotc/core/TypeComparers.scala b/src/dotty/tools/dotc/core/TypeComparers.scala index c9c2f17b6b7f..e880a4643509 100644 --- a/src/dotty/tools/dotc/core/TypeComparers.scala +++ b/src/dotty/tools/dotc/core/TypeComparers.scala @@ -11,7 +11,7 @@ object TypeComparers { private final val LogPendingSubTypesThreshold = 50 } - class TypeComparer(_ctx: Context) extends DotClass { + final class TypeComparer(_ctx: Context) extends DotClass { import TypeComparer._ implicit val ctx = _ctx diff --git a/src/dotty/tools/dotc/core/TypeOps.scala b/src/dotty/tools/dotc/core/TypeOps.scala index 77038816ea37..4cfea8f03541 100644 --- a/src/dotty/tools/dotc/core/TypeOps.scala +++ b/src/dotty/tools/dotc/core/TypeOps.scala @@ -55,7 +55,7 @@ trait TypeOps { this: Context => } } - class AsSeenFromMap(pre: Type, clazz: Symbol) extends TypeMap { + final class AsSeenFromMap(pre: Type, clazz: Symbol) extends TypeMap { def apply(tp: Type) = asSeenFrom(tp, pre, clazz, this) } @@ -133,7 +133,7 @@ trait TypeOps { this: Context => final def glb(tps: List[Type]): Type = (defn.AnyType /: tps)(glb) - def lub(tp1: Type, tp2: Type): Type = + final def lub(tp1: Type, tp2: Type): Type = if (tp1 eq tp2) tp1 else if (tp1.isWrong) tp1 else if (tp2.isWrong) tp2 @@ -194,7 +194,7 @@ trait TypeOps { this: Context => * to a list of typerefs, by converting all refinements to member * definitions in scope `decls`. */ - def normalizeToRefs(parents: List[Type], cls: ClassSymbol, decls: Scope): List[TypeRef] = { + final def normalizeToRefs(parents: List[Type], cls: ClassSymbol, decls: Scope): List[TypeRef] = { var refinements = Map[TypeName, Type]() var formals = Map[TypeName, Symbol]() def normalizeToRef(tp: Type): TypeRef = tp match { From 74aa0688da55fde610c25f6c019cbb13fdae4bf4 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Sat, 23 Feb 2013 02:53:13 +0100 Subject: [PATCH 19/22] More modifier lock down in Types. Perhaps controversially seals the hierarchy and as a consequence moves two types from the unpickler into Types.scala. --- src/dotty/tools/dotc/core/Types.scala | 127 +++++++++--------- .../tools/dotc/core/pickling/UnPickler.scala | 5 - 2 files changed, 67 insertions(+), 65 deletions(-) diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala index 664f38fc7f7f..231e9928349c 100644 --- a/src/dotty/tools/dotc/core/Types.scala +++ b/src/dotty/tools/dotc/core/Types.scala @@ -249,7 +249,7 @@ object Types { } /** The elements of an AndType or OrType */ - def factors(implicit ctx: Context): List[Type] = this match { + final def factors(implicit ctx: Context): List[Type] = this match { case tp: AndType => def components(tp: Type): List[Type] = tp match { case AndType(tp1, tp2) => components(tp1) ++ components(tp2) @@ -266,7 +266,7 @@ object Types { } /** The parameter types of a PolyType or MethodType, Empty list for others */ - def paramTypess: List[List[Type]] = this match { + final def paramTypess: List[List[Type]] = this match { case mt: MethodType => mt.paramTypes :: mt.resultType.paramTypess case pt: PolyType => pt.paramTypess case _ => Nil @@ -281,13 +281,13 @@ object Types { } /** Map function over elements of an AndType, rebuilding with & */ - def mapAnd(f: Type => Type)(implicit ctx: Context): Type = this match { + final def mapAnd(f: Type => Type)(implicit ctx: Context): Type = this match { case AndType(tp1, tp2) => tp1.mapAnd(f) & tp2.mapAnd(f) case _ => f(this) } /** Map function over elements of an OrType, rebuilding with | */ - def mapOr(f: Type => Type)(implicit ctx: Context): Type = this match { + final def mapOr(f: Type => Type)(implicit ctx: Context): Type = this match { case OrType(tp1, tp2) => tp1.mapOr(f) | tp2.mapOr(f) case _ => f(this) } @@ -402,7 +402,7 @@ object Types { * - Or phase.erasedTypes is false and both types are neither method nor * poly types. */ - def matches(that: Type)(implicit ctx: Context): Boolean = + final def matches(that: Type)(implicit ctx: Context): Boolean = ctx.typeComparer.matchesType(this, that, !ctx.phase.erasedTypes) /** Does this type match that type @@ -614,33 +614,33 @@ object Types { finishHash(hashing.mix(seed, elemHash), arity + 1, tps) } - protected def doHash(x: Any): Int = + protected final def doHash(x: Any): Int = finishHash(hashing.mix(hashSeed, x.hashCode), 1) - protected def doHash(tp: Type): Int = + protected final def doHash(tp: Type): Int = finishHash(hashSeed, 0, tp) - protected def doHash(x1: Any, tp2: Type): Int = + protected final def doHash(x1: Any, tp2: Type): Int = finishHash(hashing.mix(hashSeed, x1.hashCode), 1, tp2) - protected def doHash(tp1: Type, tp2: Type): Int = + protected final def doHash(tp1: Type, tp2: Type): Int = finishHash(hashSeed, 0, tp1, tp2) - protected def doHash(x1: Any, tp2: Type, tp3: Type): Int = + protected final def doHash(x1: Any, tp2: Type, tp3: Type): Int = finishHash(hashing.mix(hashSeed, x1.hashCode), 1, tp2, tp3) - protected def doHash(tp1: Type, tps2: List[Type]): Int = + protected final def doHash(tp1: Type, tps2: List[Type]): Int = finishHash(hashSeed, 0, tp1, tps2) - protected def doHash(x1: Any, tp2: Type, tps3: List[Type]): Int = + protected final def doHash(x1: Any, tp2: Type, tps3: List[Type]): Int = finishHash(hashing.mix(hashSeed, x1.hashCode), 1, tp2, tps3) } // end Type /** A marker trait for cached types */ - trait CachedType extends Type + sealed trait CachedType extends Type - def unique[T <: Type](tp: T)(implicit ctx: Context): T = { + final def unique[T <: Type](tp: T)(implicit ctx: Context): T = { if (tp.hash == NotCached) tp else ctx.uniques.findEntryOrUpdate(tp).asInstanceOf[T] } @@ -648,7 +648,7 @@ object Types { /** A marker trait for type proxies. * Each implementation is expected to redefine the `underlying` method. */ - abstract class TypeProxy extends Type { + sealed abstract class TypeProxy extends Type { /** The type to which this proxy forwards operations. */ def underlying(implicit ctx: Context): Type } @@ -659,42 +659,42 @@ object Types { // is for efficiency. /** Instances of this class are cached and are not proxies. */ - abstract class CachedGroundType extends Type with CachedType { + sealed abstract class CachedGroundType extends Type with CachedType { final val hash = computeHash override final def hashCode = hash def computeHash: Int } /** Instances of this class are cached and are proxies. */ - abstract class CachedProxyType extends TypeProxy with CachedType { + sealed abstract class CachedProxyType extends TypeProxy with CachedType { final val hash = computeHash override final def hashCode = hash def computeHash: Int } /** Instances of this class are uncached and are not proxies. */ - abstract class UncachedGroundType extends Type { + sealed abstract class UncachedGroundType extends Type { final def hash = NotCached } /** Instances of this class are uncached and are proxies. */ - abstract class UncachedProxyType extends TypeProxy { + sealed abstract class UncachedProxyType extends TypeProxy { final def hash = NotCached } /** A marker trait for types that are guaranteed to contain only a * single non-null value (they might contain null in addition). */ - trait SingletonType extends TypeProxy + sealed trait SingletonType extends TypeProxy /** A marker trait for types that apply only to type symbols */ - trait TypeType extends Type + sealed trait TypeType extends Type // --- NamedTypes ------------------------------------------------------------------ /** A NamedType of the form Prefix # name */ - abstract class NamedType extends CachedProxyType { + sealed abstract class NamedType extends CachedProxyType { val prefix: Type val name: Name @@ -702,7 +702,7 @@ object Types { private[this] var lastDenotation: Denotation = null /** The denotation currently denoted by this type */ - def denot(implicit ctx: Context): Denotation = { + final def denot(implicit ctx: Context): Denotation = { val validPeriods = if (lastDenotation != null) lastDenotation.validFor else Nowhere if (!(validPeriods contains ctx.period)) { @@ -728,17 +728,17 @@ object Types { protected def loadDenot(implicit ctx: Context) = prefix.member(name) - def isType = name.isTypeName - def isTerm = name.isTermName + final def isType = name.isTypeName + final def isTerm = name.isTermName def symbol(implicit ctx: Context): Symbol = denot.symbol - def info(implicit ctx: Context): Type = denot.info + final def info(implicit ctx: Context): Type = denot.info override def underlying(implicit ctx: Context): Type = info - def isAbstractType(implicit ctx: Context) = info.isRealTypeBounds + final def isAbstractType(implicit ctx: Context) = info.isRealTypeBounds - def derivedNamedType(prefix: Type, name: Name)(implicit ctx: Context): Type = + final def derivedNamedType(prefix: Type, name: Name)(implicit ctx: Context): Type = if (prefix eq this.prefix) this else NamedType(prefix, name) @@ -749,10 +749,10 @@ object Types { sealed abstract case class TypeRef(override val prefix: Type, name: TypeName) extends NamedType - trait HasFixedSym extends NamedType { + sealed trait HasFixedSym extends NamedType { protected val fixedSym: Symbol - override def symbol(implicit ctx: Context): Symbol = fixedSym - override def loadDenot(implicit ctx: Context) = { + override final def symbol(implicit ctx: Context): Symbol = fixedSym + override final def loadDenot(implicit ctx: Context) = { val denot = fixedSym.denot val owner = denot.owner if (owner.isTerm) denot else denot.asSeenFrom(prefix, owner).toDenot @@ -859,7 +859,7 @@ object Types { override def computeHash = doHash(name, info, parent) } - class CachedRefinedType(parent: Type, name: Name, infof: RefinedType => Type) extends RefinedType(parent, name)(infof) + final class CachedRefinedType(parent: Type, name: Name, infof: RefinedType => Type) extends RefinedType(parent, name)(infof) object RefinedType { def make(parent: Type, names: List[Name], infofs: List[RefinedType => Type])(implicit ctx: Context): Type = @@ -879,7 +879,7 @@ object Types { type This <: AndType - def derivedAndType(t1: Type, t2: Type)(implicit ctx: Context) = + final def derivedAndType(t1: Type, t2: Type)(implicit ctx: Context) = if ((t1 eq tp1) && (t2 eq tp2)) this else AndType(t1, t2) @@ -894,11 +894,11 @@ object Types { } sealed abstract case class OrType(tp1: Type, tp2: Type) extends CachedGroundType { - def derivedOrType(t1: Type, t2: Type)(implicit ctx: Context) = + final def derivedOrType(t1: Type, t2: Type)(implicit ctx: Context) = if ((t1 eq tp1) && (t2 eq tp2)) this else OrType(t1, t2) - override def computeHash = doHash(tp1, tp2) + override final def computeHash = doHash(tp1, tp2) } final class CachedOrType(tp1: Type, tp2: Type) extends OrType(tp1, tp2) @@ -910,14 +910,14 @@ object Types { // ----- Method types: MethodType/ExprType/PolyType/MethodParam/PolyParam --------------- - trait BindingType extends Type + sealed trait BindingType extends Type // Note: method types are cached whereas poly types are not. // The reason is that most poly types are cyclic via poly params, // and therefore two different poly types would never be equal. sealed abstract case class MethodType(paramNames: List[TermName], paramTypes: List[Type])(resultTypeExp: MethodType => Type) extends CachedGroundType with BindingType { - override lazy val resultType = resultTypeExp(this) + override final lazy val resultType = resultTypeExp(this) def isJava = false def isImplicit = false @@ -926,7 +926,7 @@ object Types { case _ => false } - override lazy val signature: List[TypeName] = { + override final lazy val signature: List[TypeName] = { def paramSig(tp: Type): TypeName = ??? val followSig = resultType match { case rtp: MethodType => rtp.signature @@ -935,7 +935,7 @@ object Types { (paramTypes map paramSig) ++ followSig } - def derivedMethodType(paramNames: List[TermName], paramTypes: List[Type], restpe: Type)(implicit ctx: Context) = + final def derivedMethodType(paramNames: List[TermName], paramTypes: List[Type], restpe: Type)(implicit ctx: Context) = if ((paramNames eq this.paramNames) && (paramTypes eq this.paramTypes) && (restpe eq this.resultType)) this else { val restpeExpr = (x: MethodType) => restpe.subst(this, x) @@ -944,11 +944,11 @@ object Types { else MethodType(paramNames, paramTypes)(restpeExpr) } - def instantiate(argTypes: List[Type])(implicit ctx: Context): Type = + final def instantiate(argTypes: List[Type])(implicit ctx: Context): Type = if (isDependent) new InstMethodMap(this, argTypes) apply resultType else resultType - override def computeHash = doHash(paramNames, resultType, paramTypes) + override final def computeHash = doHash(paramNames, resultType, paramTypes) } final class CachedMethodType(paramNames: List[TermName], paramTypes: List[Type])(resultTypeExp: MethodType => Type) @@ -964,9 +964,9 @@ object Types { override def isImplicit = true } - abstract class GenericMethodType { + sealed abstract class GenericMethodType { def apply(paramNames: List[TermName], paramTypes: List[Type])(resultTypeExp: MethodType => Type)(implicit ctx: Context): MethodType - def fromSymbols(params: List[Symbol], resultType: Type)(implicit ctx: Context) = { + final def fromSymbols(params: List[Symbol], resultType: Type)(implicit ctx: Context) = { def transResult(mt: MethodType) = resultType.subst(params, (0 until params.length).toList map (MethodParam(mt, _))) apply(params map (_.name.asTermName), params map (_.info))(transResult _) @@ -1042,7 +1042,7 @@ object Types { } } - abstract class BoundType extends UncachedProxyType { + sealed abstract class BoundType extends UncachedProxyType { type BT <: BindingType def binder: BT def copy(bt: BT): Type @@ -1076,19 +1076,19 @@ object Types { /* def typeTemplate(implicit ctx: Context): Type = classd.typeTemplate asSeenFrom (prefix, classd.symbol) */ - def typeConstructor(implicit ctx: Context): Type = + final def typeConstructor(implicit ctx: Context): Type = NamedType(prefix, classd.symbol.name) // cached because baseType needs parents - private var parentsCache: List[TypeRef] = null + private final var parentsCache: List[TypeRef] = null - override def parents(implicit ctx: Context): List[TypeRef] = { + override final def parents(implicit ctx: Context): List[TypeRef] = { if (parentsCache == null) parentsCache = classd.parents.mapConserve(_.substThis(classd.symbol, prefix).asInstanceOf[TypeRef]) parentsCache } - override def computeHash = doHash(classd.symbol, prefix) + override final def computeHash = doHash(classd.symbol, prefix) } final class CachedClassInfo(prefix: Type, classd: ClassDenotation) extends ClassInfo(prefix, classd) @@ -1099,25 +1099,25 @@ object Types { } sealed abstract case class TypeBounds(lo: Type, hi: Type) extends CachedProxyType with TypeType { - override def underlying(implicit ctx: Context): Type = hi - def derivedTypeBounds(lo1: Type, hi1: Type)(implicit ctx: Context) = + override final def underlying(implicit ctx: Context): Type = hi + final def derivedTypeBounds(lo1: Type, hi1: Type)(implicit ctx: Context) = if ((lo1 eq lo) && (hi1 eq hi)) this else TypeBounds(lo, hi) - def contains(tp: Type)(implicit ctx: Context) = lo <:< tp && tp <:< hi + final def contains(tp: Type)(implicit ctx: Context) = lo <:< tp && tp <:< hi - def &(that: TypeBounds)(implicit ctx: Context): TypeBounds = + final def &(that: TypeBounds)(implicit ctx: Context): TypeBounds = TypeBounds(this.lo | that.lo, this.hi & that.hi) - def |(that: TypeBounds)(implicit ctx: Context): TypeBounds = + final def |(that: TypeBounds)(implicit ctx: Context): TypeBounds = TypeBounds(this.lo & that.lo, this.hi | that.hi) - def substBounds(from: PolyType, to: PolyType)(implicit ctx: Context) = + final def substBounds(from: PolyType, to: PolyType)(implicit ctx: Context) = subst(from, to).asInstanceOf[TypeBounds] - def map(f: Type => Type)(implicit ctx: Context): TypeBounds = + final def map(f: Type => Type)(implicit ctx: Context): TypeBounds = TypeBounds(f(lo), f(hi)) - override def computeHash = doHash(lo, hi) + override final def computeHash = doHash(lo, hi) } final class CachedTypeBounds(lo: Type, hi: Type) extends TypeBounds(lo, hi) @@ -1155,6 +1155,13 @@ object Types { final case class ImportType(expr: TypedTree) extends UncachedGroundType + // Unpickler Types ----------------------------------------------------------------- + final case class TempPolyType(tparams: List[Symbol], tpe: Type) extends UncachedGroundType + + /** Temporary type for classinfos, will be decomposed on completion of the class */ + final case class TempClassInfoType(parentTypes: List[Type], decls: Scope, clazz: Symbol) extends UncachedGroundType + + // Special type objects ------------------------------------------------------------ case object NoType extends UncachedGroundType { @@ -1167,7 +1174,7 @@ object Types { override def computeHash = hashSeed } - abstract class ErrorType extends UncachedGroundType + sealed abstract class ErrorType extends UncachedGroundType object ErrorType extends ErrorType @@ -1224,14 +1231,14 @@ object Types { } - class InstMethodMap(mt: MethodType, argtypes: List[Type])(implicit ctx: Context) extends TypeMap { + final class InstMethodMap(mt: MethodType, argtypes: List[Type])(implicit ctx: Context) extends TypeMap { def apply(tp: Type) = tp match { case MethodParam(`mt`, n) => argtypes(n) case _ => mapOver(tp) } } - class InstPolyMap(pt: PolyType, argtypes: List[Type])(implicit ctx: Context) extends TypeMap { + final class InstPolyMap(pt: PolyType, argtypes: List[Type])(implicit ctx: Context) extends TypeMap { def apply(tp: Type) = tp match { case PolyParam(`pt`, n) => argtypes(n) case _ => mapOver(tp) @@ -1280,7 +1287,7 @@ object Types { } } - class ExistsAccumulator(p: Type => Boolean) extends TypeAccumulator[Boolean] { + final class ExistsAccumulator(p: Type => Boolean) extends TypeAccumulator[Boolean] { def apply(x: Boolean, tp: Type) = x || p(tp) || foldOver(x, tp) } diff --git a/src/dotty/tools/dotc/core/pickling/UnPickler.scala b/src/dotty/tools/dotc/core/pickling/UnPickler.scala index 1145b264d5f5..09d748bbab20 100644 --- a/src/dotty/tools/dotc/core/pickling/UnPickler.scala +++ b/src/dotty/tools/dotc/core/pickling/UnPickler.scala @@ -21,11 +21,6 @@ object UnPickler { /** Exception thrown if classfile is corrupted */ class BadSignature(msg: String) extends RuntimeException(msg) - final case class TempPolyType(tparams: List[Symbol], tpe: Type) extends UncachedGroundType - - /** Temporary type for classinfos, will be decomposed on completion of the class */ - final case class TempClassInfoType(parentTypes: List[Type], decls: Scope, clazz: Symbol) extends UncachedGroundType - def depoly(tp: Type)(implicit ctx: Context): Type = tp match { case TempPolyType(tparams, restpe) => PolyType.fromSymbols(tparams, restpe) case tp => tp From 717f6900629c6251628461bfd57a85bea81148f7 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Sat, 23 Feb 2013 11:54:10 +0100 Subject: [PATCH 20/22] More modifier lock down in pickling._ --- .../core/pickling/AbstractFileReader.scala | 2 +- .../core/pickling/ClassfileConstants.scala | 8 ++--- .../dotc/core/pickling/ClassfileParser.scala | 2 +- .../dotc/core/pickling/PickleBuffer.scala | 33 +++++++++---------- .../tools/dotc/core/pickling/UnPickler.scala | 2 +- 5 files changed, 23 insertions(+), 24 deletions(-) diff --git a/src/dotty/tools/dotc/core/pickling/AbstractFileReader.scala b/src/dotty/tools/dotc/core/pickling/AbstractFileReader.scala index 60633370d58a..a0fc079175ba 100644 --- a/src/dotty/tools/dotc/core/pickling/AbstractFileReader.scala +++ b/src/dotty/tools/dotc/core/pickling/AbstractFileReader.scala @@ -14,7 +14,7 @@ import io.AbstractFile * @author Philippe Altherr * @version 1.0, 23/03/2004 */ -class AbstractFileReader(val file: AbstractFile) { +final class AbstractFileReader(val file: AbstractFile) { /** the buffer containing the file */ diff --git a/src/dotty/tools/dotc/core/pickling/ClassfileConstants.scala b/src/dotty/tools/dotc/core/pickling/ClassfileConstants.scala index 5e97f373d28a..b9fa88026463 100644 --- a/src/dotty/tools/dotc/core/pickling/ClassfileConstants.scala +++ b/src/dotty/tools/dotc/core/pickling/ClassfileConstants.scala @@ -324,7 +324,7 @@ object ClassfileConstants { final val impdep1 = 0xfe final val impdep2 = 0xff - abstract class FlagTranslation { + sealed abstract class FlagTranslation { import Flags._ private var isAnnotation = false @@ -360,16 +360,16 @@ object ClassfileConstants { res } - def classFlags(jflags: Int): FlagSet = { + final def classFlags(jflags: Int): FlagSet = { initFields(jflags) isClass = true translateFlags(jflags, EmptyFlags) } - def fieldFlags(jflags: Int): FlagSet = { + final def fieldFlags(jflags: Int): FlagSet = { initFields(jflags) translateFlags(jflags, if ((jflags & JAVA_ACC_FINAL) == 0) Mutable else EmptyFlags) } - def methodFlags(jflags: Int): FlagSet = { + final def methodFlags(jflags: Int): FlagSet = { initFields(jflags) translateFlags(jflags, if ((jflags & JAVA_ACC_BRIDGE) != 0) Bridge else EmptyFlags) } diff --git a/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala b/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala index 0aba91fea3e2..8a2f725f171e 100644 --- a/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala +++ b/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala @@ -13,7 +13,7 @@ import scala.collection.mutable.{ ListBuffer, ArrayBuffer } import scala.annotation.switch import io.AbstractFile -class ClassfileParser( +final class ClassfileParser( classfile: AbstractFile, classRoot: LazyClassDenotation, moduleRoot: LazyClassDenotation)(implicit cctx: CondensedContext) { diff --git a/src/dotty/tools/dotc/core/pickling/PickleBuffer.scala b/src/dotty/tools/dotc/core/pickling/PickleBuffer.scala index 9e58c549144b..92748fc03981 100644 --- a/src/dotty/tools/dotc/core/pickling/PickleBuffer.scala +++ b/src/dotty/tools/dotc/core/pickling/PickleBuffer.scala @@ -11,7 +11,7 @@ import Flags._ * @param from The first index where defined data are found * @param to The first index where new data can be written */ -class PickleBuffer(data: Array[Byte], from: Int, to: Int) { +abstract class PickleBuffer(data: Array[Byte], from: Int, to: Int) { var bytes = data var readIndex = from @@ -24,13 +24,13 @@ class PickleBuffer(data: Array[Byte], from: Int, to: Int) { bytes = bytes1 } - def ensureCapacity(capacity: Int) = + final def ensureCapacity(capacity: Int) = while (bytes.length < writeIndex + capacity) dble() // -- Basic output routines -------------------------------------------- /** Write a byte of data */ - def writeByte(b: Int) { + final def writeByte(b: Int) { if (writeIndex == bytes.length) dble() bytes(writeIndex) = b.toByte writeIndex += 1 @@ -39,7 +39,7 @@ class PickleBuffer(data: Array[Byte], from: Int, to: Int) { /** Write a natural number in big endian format, base 128. * All but the last digits have bit 0x80 set. */ - def writeNat(x: Int) = + final def writeNat(x: Int) = writeLongNat(x.toLong & 0x00000000FFFFFFFFL) /** @@ -49,7 +49,7 @@ class PickleBuffer(data: Array[Byte], from: Int, to: Int) { * if the long value is in the range Int.MIN_VALUE to * Int.MAX_VALUE. */ - def writeLongNat(x: Long) { + final def writeLongNat(x: Long) { def writeNatPrefix(x: Long) { val y = x >>> 7 if (y != 0L) writeNatPrefix(y) @@ -66,7 +66,7 @@ class PickleBuffer(data: Array[Byte], from: Int, to: Int) { * @param pos ... * @param x ... */ - def patchNat(pos: Int, x: Int) { + final def patchNat(pos: Int, x: Int) { def patchNatPrefix(x: Int) { writeByte(0) Array.copy(bytes, pos, bytes, pos+1, writeIndex - (pos+1)) @@ -83,7 +83,7 @@ class PickleBuffer(data: Array[Byte], from: Int, to: Int) { * * @param x The long number to be written. */ - def writeLong(x: Long) { + final def writeLong(x: Long) { val y = x >> 8 val z = x & 0xff if (-y != (z >> 7)) writeLong(y) @@ -93,18 +93,18 @@ class PickleBuffer(data: Array[Byte], from: Int, to: Int) { // -- Basic input routines -------------------------------------------- /** Peek at the current byte without moving the read index */ - def peekByte(): Int = bytes(readIndex) + final def peekByte(): Int = bytes(readIndex) /** Read a byte */ - def readByte(): Int = { + final def readByte(): Int = { val x = bytes(readIndex); readIndex += 1; x } /** Read a natural number in big endian format, base 128. * All but the last digits have bit 0x80 set.*/ - def readNat(): Int = readLongNat().toInt + final def readNat(): Int = readLongNat().toInt - def readLongNat(): Long = { + final def readLongNat(): Long = { var b = 0L var x = 0L do { @@ -115,7 +115,7 @@ class PickleBuffer(data: Array[Byte], from: Int, to: Int) { } /** Read a long number in signed big endian format, base 256. */ - def readLong(len: Int): Long = { + final def readLong(len: Int): Long = { var x = 0L var i = 0 while (i < len) { @@ -129,8 +129,7 @@ class PickleBuffer(data: Array[Byte], from: Int, to: Int) { /** Returns the buffer as a sequence of (Int, Array[Byte]) representing * (tag, data) of the individual entries. Saves and restores buffer state. */ - - def toIndexedSeq: IndexedSeq[(Int, Array[Byte])] = { + final def toIndexedSeq: IndexedSeq[(Int, Array[Byte])] = { val saved = readIndex readIndex = 0 readNat() ; readNat() // discarding version @@ -157,14 +156,14 @@ class PickleBuffer(data: Array[Byte], from: Int, to: Int) { * @param op ... * @return ... */ - def until[T](end: Int, op: () => T): List[T] = + final def until[T](end: Int, op: () => T): List[T] = if (readIndex == end) List() else op() :: until(end, op); /** Perform operation op the number of * times specified. Concatenate the results into a list. */ - def times[T](n: Int, op: ()=>T): List[T] = + final def times[T](n: Int, op: ()=>T): List[T] = if (n == 0) List() else op() :: times(n-1, op) - def unpickleScalaFlags(sflags: Long): FlagSet = ??? + final def unpickleScalaFlags(sflags: Long): FlagSet = ??? } diff --git a/src/dotty/tools/dotc/core/pickling/UnPickler.scala b/src/dotty/tools/dotc/core/pickling/UnPickler.scala index 09d748bbab20..9e418bcdb872 100644 --- a/src/dotty/tools/dotc/core/pickling/UnPickler.scala +++ b/src/dotty/tools/dotc/core/pickling/UnPickler.scala @@ -67,7 +67,7 @@ object UnPickler { * @param moduleroot the top-level module class which is unpickled, or NoSymbol if inapplicable * @param filename filename associated with bytearray, only used for error messages */ -class UnPickler(bytes: Array[Byte], classRoot: LazyClassDenotation, moduleRoot: LazyClassDenotation)(implicit cctx: CondensedContext) +final class UnPickler(bytes: Array[Byte], classRoot: LazyClassDenotation, moduleRoot: LazyClassDenotation)(implicit cctx: CondensedContext) extends PickleBuffer(bytes, 0, -1) { import UnPickler._ From 4598e8c23b94c209bc6378e044ab0df2258b2963 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Sat, 23 Feb 2013 12:59:40 +0100 Subject: [PATCH 21/22] Address exhaustiveness warnings when matching on Trees. - Introduce a marker trait for Tree[Nothing] nodes, and use this in TreeAccumulator. - seal GenericApply - Make the match demo plugin transformer @unchecked - Add tree checking for Try - Match on EmptyTree() rather than tpd.EmptyTree --- .../dotc/core/PluggableTransformers.scala | 2 +- src/dotty/tools/dotc/core/Trees.scala | 23 +++++++++++++------ src/dotty/tools/dotc/core/TypedTrees.scala | 8 ++++++- 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/src/dotty/tools/dotc/core/PluggableTransformers.scala b/src/dotty/tools/dotc/core/PluggableTransformers.scala index 3e3ee7df1ea3..1c66f59ba31c 100644 --- a/src/dotty/tools/dotc/core/PluggableTransformers.scala +++ b/src/dotty/tools/dotc/core/PluggableTransformers.scala @@ -77,7 +77,7 @@ object PluggableTransformers { case _ => postProcess(tree, old, c, plugins) } - protected def postProcess(tree: Tree[T], old: Tree[T], c: Context, plugins: Plugins): Tree[T] = tree match { + protected def postProcess(tree: Tree[T], old: Tree[T], c: Context, plugins: Plugins): Tree[T] = (tree: @unchecked) match { case tree: Ident[_] => finishIdent(tree, old, c, plugins) case tree: Select[_] => finishSelect(tree, old, c, plugins) } diff --git a/src/dotty/tools/dotc/core/Trees.scala b/src/dotty/tools/dotc/core/Trees.scala index 284e1b6a4d13..7c339c544431 100644 --- a/src/dotty/tools/dotc/core/Trees.scala +++ b/src/dotty/tools/dotc/core/Trees.scala @@ -206,7 +206,7 @@ object Trees { def forwardTo = qual } - abstract class GenericApply[T] extends ProxyTree[T] with TermTree[T] { + sealed abstract class GenericApply[T] extends ProxyTree[T] with TermTree[T] { type ThisTree[T] <: GenericApply[T] val fun: Tree[T] val args: List[Tree[T]] @@ -485,7 +485,7 @@ object Trees { } /** A missing tree */ - abstract case class EmptyTree[T]() + sealed abstract case class EmptyTree[T]() extends Tree[T] with AlwaysEmpty[T] { type ThisTree[T] = EmptyTree[T] } @@ -496,7 +496,7 @@ object Trees { def apply[T]: EmptyTree[T] = theEmptyTree.asInstanceOf } - abstract class EmptyValDef[T] extends ValDef[T]( + sealed abstract class EmptyValDef[T] extends ValDef[T]( Modifiers[T](Private), nme.WILDCARD, EmptyTree[T], EmptyTree[T])(NoPosition) with AlwaysEmpty[T] private object theEmptyValDef extends EmptyValDef[Nothing] @@ -506,7 +506,7 @@ object Trees { } /** A tree that can be shared without its position - * polluting containing trees. Accumulators and tranformers + * polluting containing trees. Accumulators and transformers * memoize results of shared subtrees */ final case class Shared[T](shared: Tree[T]) extends Tree[T] { @@ -518,20 +518,25 @@ object Trees { // ----- Tree cases that exist in untyped form only ------------------ + /** A marker trait for all Tree[Nothing] descendants. Useful for exhaustively pattern matching over Tree[U] */ + sealed trait UntypedTreeMarker { + self: UntypedTree => + } + /** A typed subtree of an untyped tree needs to be wrapped in a TypedSlice */ - final class TypedSplice(tree: TypedTree) extends UntypedTree { + final class TypedSplice(tree: TypedTree) extends UntypedTree with UntypedTreeMarker { val pos = tree.pos } /** mods object name impl */ final case class ModuleDef(mods: Modifiers[Nothing], name: TermName, impl: Template[Nothing])(implicit cpos: Position) - extends DefTree[Nothing] { + extends DefTree[Nothing] with UntypedTreeMarker { val pos = cpos union impl.pos } /** (vparams) => body */ final case class Function(vparams: List[ValDef[Nothing]], body: Tree[Nothing])(implicit cpos: Position) - extends TermTree[Nothing] { + extends TermTree[Nothing] with UntypedTreeMarker { val pos = unionPos(cpos union body.pos, vparams) } @@ -800,6 +805,8 @@ object Trees { tree1 }, tree, c, plugins) + case _: UntypedTreeMarker => + tree // TODO should this abort? } def transform(trees: List[Tree[T]], c: C): List[Tree[T]] = trees mapConserve (transform(_, c)) @@ -948,6 +955,8 @@ object Trees { sharedMemo = sharedMemo.updated(tree, x1) x1 } + case _: UntypedTreeMarker => + x } } } diff --git a/src/dotty/tools/dotc/core/TypedTrees.scala b/src/dotty/tools/dotc/core/TypedTrees.scala index 65ab956933c9..f95089643053 100644 --- a/src/dotty/tools/dotc/core/TypedTrees.scala +++ b/src/dotty/tools/dotc/core/TypedTrees.scala @@ -573,9 +573,15 @@ object TypedTrees { check(annot.symbol.isClassConstructor) check(annot.symbol.owner.isSubClass(defn.AnnotationClass)) check(arg.isType || arg.isValue) - case tpd.EmptyTree => case Shared(shared) => check(shared.isType || shared.isTerm) + case Try(block, catches, finalizer) => + check(block.isTerm) + check(finalizer.isTerm) + def checkType(t: Tree[Type]) = check(t.tpe <:< tree.tpe) + checkType(block) + catches foreach checkType + case EmptyTree() => } implicit class TreeInfo(val tree: tpd.Tree) extends AnyVal { From 02e5187a2b9321dff64e1dbea4406f4cb170dd65 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Sat, 23 Feb 2013 20:19:36 +0100 Subject: [PATCH 22/22] Fix SOEs LazySymDenotation#{info, tryComplete} - info was calling itself, rather than the field _info - tryComplete must interrogate and set the Locked bit through the raw _flags. --- .../tools/dotc/core/SymDenotations.scala | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala index f35e5bb2081d..4fcaef75b166 100644 --- a/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/src/dotty/tools/dotc/core/SymDenotations.scala @@ -52,7 +52,7 @@ object SymDenotations { if (this == NoSymbol || owner == NoSymbol || owner.isEffectiveRoot) name else (effectiveOwner.enclosingClass.fullName(separator) :+ separator) ++ name - /** `fullName` where `.' is the separator character */ + /** `fullName` where `.` is the separator character */ def fullName(implicit ctx: Context): Name = fullName('.') /** The source or class file from which this denotation was generated, null if not applicable. */ @@ -83,8 +83,12 @@ object SymDenotations { /** Set given flags(s) of this denotation */ final def setFlag(flags: FlagSet): Unit = { _flags |= flags } - /** UnsSet given flags(s) of this denotation */ - final def resetFlag(flags: FlagSet): Unit = { _flags &~= flags } + /** Unset given flags(s) of this denotation */ + final def resetFlag(flags: FlagSet): Unit = { _flags &~= flags } + + protected final def isLocked: Boolean = _flags is Locked // don't use `flags` or we'll hit an SOE. + protected final def lock(): Unit = setFlag(Locked) + protected final def unlock(): Unit = resetFlag(Locked) private[this] var _annotations: List[Annotation] = Nil @@ -836,7 +840,7 @@ object SymDenotations { private[this] var _info: Type = _ protected[core] def info_=(tp: Type) = if (_info == null) _info = tp - override def info = { if (info == null) tryComplete(); _info } + override def info = { if (_info == null) tryComplete(); _info } } def LazySymDenotation(symbol: Symbol, owner: Symbol, name: Name, initFlags: FlagSet, @@ -855,7 +859,7 @@ object SymDenotations { assocFile: AbstractFile)(initctx: Context) extends ClassDenotation(initFlags, assocFile)(initctx) { val selfType = if (optSelfType == NoType) typeConstructor(initctx) else optSelfType - final def preCompleteDecls = decls + def preCompleteDecls = decls } def CompleteClassDenotation( @@ -920,15 +924,15 @@ object SymDenotations { override protected[core] final def tryComplete(): Unit = try { - if (flags is Locked) throw new CyclicReference(symbol) - setFlag(Locked) + if (isLocked) throw new CyclicReference(symbol) + lock() val c = completer if (c == null) throw new CompletionError(this) completer = null // set completer to null to avoid space leaks // and to make any subsequent completion attempt a CompletionError c(this) } finally { - flags &~= Locked + unlock() } private[this] var _privateWithin: Symbol = _