Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
92 commits
Select commit Hold shift + click to select a range
5866d0d
Allow refinements of new types
odersky May 24, 2016
d30f441
Allow general recursion in refined types.
odersky Jun 29, 2016
5d03186
Better printing of skolems
odersky May 26, 2016
cdb4a1c
New type lambda scheme for hk types
odersky Jun 29, 2016
850dc6f
Introduce recursive types
odersky Jun 29, 2016
af43d32
Abstract type parameters out from type symbols
odersky Jun 29, 2016
aa7f66d
Disable checkInst in RecType
odersky Jun 29, 2016
08a0ea6
Add printing of type lambda trees
odersky Jun 29, 2016
178e90e
Remove special case in parser
odersky May 27, 2016
4bf43f8
Turn on new hk scheme
odersky Jun 29, 2016
5daae27
Multiple fixes
odersky Jun 29, 2016
e56bd1f
Beta-reduce when simplifying
odersky Jun 2, 2016
e61b80a
Refinement of cycle avoidance
odersky Jun 2, 2016
a7d61c0
Make etaExpandIfHk work for non-symbol type params
odersky Jun 2, 2016
d0f82a5
Don't map info of SkolemTypes in type maps
odersky Jun 3, 2016
c136af1
Fixes to BetaReduce and asMemberOf; add a second betaReduce
odersky Jun 29, 2016
ae1f248
Normalize RecTypes on creation to avoid cycles.
odersky Jun 4, 2016
939d9da
Add a second betaReduce
odersky Jun 4, 2016
c35f817
Adapt widenForMatchSelector to new HK scheme
odersky Jun 5, 2016
e36a36a
Fix typeParams for abstract types under completion
odersky Jun 5, 2016
6a7e466
Avoid accidental creation of hk types
odersky Jun 29, 2016
8e84fb0
Eta-expand unapplied types that have type parameters
odersky Jun 29, 2016
68e73e8
Restrict betaReduce to hk applications
odersky Jun 29, 2016
463e99a
Optionally, check kinds match for & and |
odersky Jun 7, 2016
0a5f839
Avoid infinite recursion when comparing recursive types.
odersky Jun 29, 2016
31af865
Fix condition for lambda abstracting in Namer
odersky Jun 29, 2016
5041e93
Make TypeAccumulators follow LazyRefs
odersky Jun 7, 2016
f1bf78b
Avoid creating dependent function types for closures
odersky Jun 8, 2016
830b724
Change tests
odersky Jun 29, 2016
6414f3b
Deal with nested findMember calls over the same RecType
odersky Jun 9, 2016
e749d83
Various tweaks
odersky Jun 29, 2016
d1f809f
Remove old hk scheme
odersky Jun 29, 2016
60d81f8
Start new, direct HK scheme
odersky Jun 29, 2016
3490e01
Make Constraint#bounds work for aliases
odersky Jun 14, 2016
f6efd99
Fix appliedTo and typeParams, and higher kinded subtyping tests
odersky Jun 29, 2016
97e84e6
Fix printing of type lambda trees and types
odersky Jun 18, 2016
73dd039
Various hk related fixes in types
odersky Jun 29, 2016
02ce995
Refactoring of PolyType and TypeLambda
odersky Jun 29, 2016
c28dd1b
Tweaks to appliedTo
odersky Jun 29, 2016
c1e27a0
Change underlying of HKApply
odersky Jun 29, 2016
98b466c
Ensure wildApprox maintains kinds
odersky Jun 20, 2016
0965e1a
Handle TypeLambdas in findMember
odersky Jun 20, 2016
65c26ba
Avoid cyclic errors when reading nsc.Global
odersky Jun 21, 2016
1e48758
Refactor handling of unpickled type params
odersky Jun 29, 2016
960ea75
Allow for HK types in widenForMatchSelector
odersky Jun 22, 2016
e0db04d
Drop bounds checking for type lambdas
odersky Jun 22, 2016
de5d8fe
Skip typeBounds when computing upperBound
odersky Jun 22, 2016
8805dd4
When comparing types revert eta-expansion as needed
odersky Jun 26, 2016
646bf97
Beta-reduce with wildcard arguments if this is safe.
odersky Jun 29, 2016
09f7ab1
Handle findMember for unreduced hk types.
odersky Jun 27, 2016
9a90e81
Handle WildcardType in liftToClasses
odersky Jun 29, 2016
dca1052
Don't make * types higher-kinded in avoid
odersky Jun 29, 2016
4093e13
Don't dealias when applying types
odersky Jun 29, 2016
bb59931
Fixes to hk comparisons
odersky Jun 29, 2016
dc5be65
Special case for TypeRefs in upperbound
odersky Jun 28, 2016
31ecad5
Drop assertion in TypeMap
odersky Jun 29, 2016
9d9965c
Fix parameter unpickling
odersky Jun 28, 2016
a23c1a4
Fixes for printing under -Ytest-pickler
odersky Jun 29, 2016
6bd7ba9
Remove refinement encoding of hk types
odersky Jun 29, 2016
ae360e9
Handle signatures over uninstantiated type variables
odersky Jun 29, 2016
6abde38
Get rid of BindingKind
odersky Jun 29, 2016
68abba1
Simplify appliedTo
odersky Jun 29, 2016
30e15ab
Cleanup of Signature matching
odersky Jun 30, 2016
b6a8bc7
Revert complications in asMemberOf
odersky Jun 30, 2016
32c0135
Refactorings of GenericTypes and underlying/upperbound
odersky Jun 30, 2016
34a068b
Drop Config.checkKinds
odersky Jun 30, 2016
beff8f8
Avoid orphan parameters in Constraint#replace
odersky Jul 2, 2016
eebb4b0
Fix bug in printing untyped New nodes.
odersky Jul 3, 2016
fd62c7b
Disallow higher-kinded types that simulate general existential types
odersky Jul 7, 2016
4693a78
Less eager removal of type parameters from constraint
odersky Jul 7, 2016
2ddb849
Unify aliases when taking a lub.
odersky Jul 4, 2016
c541ef9
Do the right thing for NoDenotation.mapInfo
odersky Jul 7, 2016
78b2672
Add a case where caching was missing.
odersky Jul 5, 2016
223705d
Refactor Typevar instantiation
odersky Jul 7, 2016
5e90215
Drop compareAliasedRefined
odersky Jul 8, 2016
540b38c
More tests
odersky Jul 9, 2016
a200695
Fix SI-2712
odersky Jul 11, 2016
6d7bc49
Address reviewers comments
odersky Jul 11, 2016
055726e
ExtractAPI: Do not miss value parameters of PolyTypes
smarter Jul 12, 2016
a6a142e
ExtractAPI: Add support for TypeLambdas
smarter Jul 12, 2016
1792c9e
ExtractAPI: Add support for RecType
smarter Jul 12, 2016
cdebd91
Allow definition of new types in refinements
odersky Jul 11, 2016
84a1a7a
Avoid dealiasing on type application
odersky Jul 12, 2016
c7f3b45
Drop restriction to 2nd order hk types
odersky Jul 12, 2016
7df0fa5
Enable test for fixed #1181: Typer should preserve aliases in TypeTrees
smarter Jul 12, 2016
1443fd4
Optimize hk comparisons
odersky Jul 12, 2016
f50cb20
Make rewritings of hk applications configurable
odersky Jul 13, 2016
0ff5354
Simplify variance computations
odersky Jul 13, 2016
18b3080
Allow hk parameters in lower bounds
odersky Jul 13, 2016
82fc27f
Fix bounds checking of hk applied typed
odersky Jul 14, 2016
a737b47
Add test case for hk bounds checking
odersky Jul 14, 2016
894c9fb
Bounds of type lambdas compare contravariantly
odersky Jul 15, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Refactor handling of unpickled type params
Under the new hk scheme we discovered that type parameters
are sometimes unpickled in the wrong order. The fault was always
present but the previous hk schemes were somehow lenient
enough in their subtyping rules to not discover the problem.
E.g., when reading Coder.scala, dotc believed that parameter
`A` of `TraversableOnce#BufferedCanBuildFrom` is higher-kinded
and parameter `CC` is first-order where the opposite is true.

This commit hardens the way we read type parameters in order
to make this swap impossible by design.

- Revert auto-healing in derivedAppliedType

The healing hid a real error about order of type parameters
in Scala2 unpickling which was fixed in the previous commits.
The healing caused Map.scala to fail because it is possible
that type parameters are mis-prediced to be Nil in an F-bounded
context.

- Smallish fixes to type applications
  • Loading branch information
odersky committed Jul 11, 2016
commit 1e48758ad5c100a7dd4d1a5b846ef5ff37e37721
36 changes: 23 additions & 13 deletions src/dotty/tools/dotc/core/SymDenotations.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1213,15 +1213,25 @@ object SymDenotations {

private[this] var myNamedTypeParams: Set[TypeSymbol] = _

/** The type parameters in this class, in the order they appear in the current
* scope `decls`. This is might be temporarily the incorrect order when
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: "This might"

* reading Scala2 pickled info. The problem is fixed by `updateTypeParams`
* which is called once an unpickled symbol has been completed.
*/
private def typeParamsFromDecls(implicit ctx: Context) =
unforcedDecls.filter(sym =>
(sym is TypeParam) && sym.owner == symbol).asInstanceOf[List[TypeSymbol]]

/** The type parameters of this class */
override final def typeParams(implicit ctx: Context): List[TypeSymbol] = {
def computeTypeParams = {
if (ctx.erasedTypes || is(Module)) Nil // fast return for modules to avoid scanning package decls
else if (this ne initial) initial.asSymDenotation.typeParams
else unforcedDecls.filter(sym =>
(sym is TypeParam) && sym.owner == symbol).asInstanceOf[List[TypeSymbol]]
}
if (myTypeParams == null) myTypeParams = computeTypeParams
if (myTypeParams == null)
myTypeParams =
if (ctx.erasedTypes || is(Module)) Nil // fast return for modules to avoid scanning package decls
else if (this ne initial) initial.asSymDenotation.typeParams
else infoOrCompleter match {
case info: TypeParamsCompleter => info.completerTypeParams(symbol)
case _ => typeParamsFromDecls
}
myTypeParams
}

Expand Down Expand Up @@ -1537,16 +1547,16 @@ object SymDenotations {
if (myMemberCache != null) myMemberCache invalidate sym.name
}

/** Make sure the type parameters of this class are `tparams`, reorder definitions
* in scope if necessary.
/** Make sure the type parameters of this class appear in the order given
* by `tparams` in the scope of the class. Reorder definitions in scope if necessary.
* @pre All type parameters in `tparams` are entered in class scope `info.decls`.
*/
def updateTypeParams(tparams: List[Symbol])(implicit ctx: Context): Unit =
if (!typeParams.corresponds(tparams)(_.name == _.name)) {
if (!ctx.erasedTypes && !typeParamsFromDecls.corresponds(typeParams)(_.name == _.name)) {
Copy link
Member

@smarter smarter Jul 11, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be .corresponds(tparams) like it was before ?

val decls = info.decls
val decls1 = newScope
for (tparam <- tparams) decls1.enter(decls.lookup(tparam.name))
for (sym <- decls) if (!typeParams.contains(sym)) decls1.enter(sym)
for (sym <- decls) if (!tparams.contains(sym)) decls1.enter(sym)
info = classInfo.derivedClassInfo(decls = decls1)
myTypeParams = null
}
Expand Down Expand Up @@ -1868,9 +1878,9 @@ object SymDenotations {
/** A subclass of LazyTypes where type parameters can be completed independently of
* the info.
*/
abstract class TypeParamsCompleter extends LazyType {
trait TypeParamsCompleter extends LazyType {
/** The type parameters computed by the completer before completion has finished */
def completerTypeParams(sym: Symbol): List[TypeSymbol]
def completerTypeParams(sym: Symbol)(implicit ctx: Context): List[TypeSymbol]
}

val NoSymbolFn = (ctx: Context) => NoSymbol
Expand Down
9 changes: 5 additions & 4 deletions src/dotty/tools/dotc/core/TypeApplications.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ package core
import Types._
import Contexts._
import Symbols._
import SymDenotations.TypeParamsCompleter
import SymDenotations.{LazyType, TypeParamsCompleter}
import Decorators._
import util.Stats._
import util.common._
Expand Down Expand Up @@ -191,7 +191,8 @@ object TypeApplications {
else {
def bounds(tparam: MemberBinding) = tparam match {
case tparam: Symbol => tparam.infoOrCompleter
case tparam: RefinedType => tparam.memberBounds
case tparam: RefinedType if !Config.newHK => tparam.memberBounds
case tparam: LambdaParam => tparam.memberBounds
}
args.zipWithConserve(tparams)((arg, tparam) => arg.etaExpandIfHK(bounds(tparam)))
}
Expand Down Expand Up @@ -380,7 +381,7 @@ class TypeApplications(val self: Type) extends AnyVal {
case self: WildcardType => self.optBounds.knownHK
case self: PolyParam => self.underlying.knownHK
case self: TypeProxy => self.underlying.knownHK
case NoType => 0
case NoType | _: LazyType => 0
case _ => -1
}

Expand Down Expand Up @@ -742,7 +743,7 @@ class TypeApplications(val self: Type) extends AnyVal {
self.derivedTypeBounds(self.lo, self.hi.appliedTo(args))
case self: LazyRef =>
LazyRef(() => self.ref.appliedTo(args, typParams))
case _ if typParams.nonEmpty && typParams.head.isInstanceOf[LambdaParam] =>
case _ if typParams.isEmpty || typParams.head.isInstanceOf[LambdaParam] =>
HKApply(self, args)
case _ =>
matchParams(self, typParams, args) match {
Expand Down
8 changes: 6 additions & 2 deletions src/dotty/tools/dotc/core/Types.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1436,6 +1436,9 @@ object Types {
else computeDenot
}

/** Hook for adding debug check code when denotations are assigned */
final def checkDenot()(implicit ctx: Context) = {}

/** A second fallback to recompute the denotation if necessary */
private def computeDenot(implicit ctx: Context): Denotation = {
val savedEphemeral = ctx.typerState.ephemeral
Expand Down Expand Up @@ -1471,6 +1474,7 @@ object Types {

// Don't use setDenot here; double binding checks can give spurious failures after erasure
lastDenotation = d
checkDenot()
lastSymbol = d.symbol
checkedPeriod = ctx.period
}
Expand Down Expand Up @@ -1542,6 +1546,7 @@ object Types {
// additional checks that intercept `denot` can be added here

lastDenotation = denot
checkDenot()
lastSymbol = denot.symbol
checkedPeriod = Nowhere
}
Expand Down Expand Up @@ -3462,8 +3467,7 @@ object Types {
protected def derivedSuperType(tp: SuperType, thistp: Type, supertp: Type): Type =
tp.derivedSuperType(thistp, supertp)
protected def derivedAppliedType(tp: HKApply, tycon: Type, args: List[Type]): Type =
if (tycon.typeParams.isEmpty) tycon
else tp.derivedAppliedType(tycon, args)
tp.derivedAppliedType(tycon, args)
protected def derivedAndOrType(tp: AndOrType, tp1: Type, tp2: Type): Type =
tp.derivedAndOrType(tp1, tp2)
protected def derivedAnnotatedType(tp: AnnotatedType, underlying: Type, annot: Annotation): Type =
Expand Down
4 changes: 2 additions & 2 deletions src/dotty/tools/dotc/core/classfile/ClassfileParser.scala
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,7 @@ class ClassfileParser(
}
index += 1
}
val ownTypeParams = newTParams.toList
val ownTypeParams = newTParams.toList.asInstanceOf[List[TypeSymbol]]
val tpe =
if ((owner == null) || !owner.isClass)
sig2type(tparams, skiptvs = false)
Expand Down Expand Up @@ -584,7 +584,7 @@ class ClassfileParser(
* a vararg argument. We solve this by creating two constructors, one with
* an array, the other with a repeated parameter.
*/
def addAnnotationConstructor(classInfo: Type, tparams: List[Symbol] = Nil)(implicit ctx: Context): Unit = {
def addAnnotationConstructor(classInfo: Type, tparams: List[TypeSymbol] = Nil)(implicit ctx: Context): Unit = {
def addDefaultGetter(attr: Symbol, n: Int) =
ctx.newSymbol(
owner = moduleRoot.symbol,
Expand Down
48 changes: 33 additions & 15 deletions src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ object Scala2Unpickler {
/** Exception thrown if classfile is corrupted */
class BadSignature(msg: String) extends RuntimeException(msg)

case class TempPolyType(tparams: List[Symbol], tpe: Type) extends UncachedGroundType {
case class TempPolyType(tparams: List[TypeSymbol], tpe: Type) extends UncachedGroundType {
override def fallbackToText(printer: Printer): Text =
"[" ~ printer.dclsText(tparams, ", ") ~ "]" ~ printer.toText(tpe)
}
Expand Down Expand Up @@ -195,19 +195,18 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas
case _ => errorBadSignature(s"a runtime exception occurred: $ex", Some(ex))
}

private var postReadOp: Context => Unit = null

def run()(implicit ctx: Context) =
try {
var i = 0
while (i < index.length) {
if (entries(i) == null && isSymbolEntry(i)) {
val savedIndex = readIndex
readIndex = index(i)
entries(i) = readSymbol()
if (postReadOp != null) {
postReadOp(ctx)
postReadOp = null
val sym = readSymbol()
entries(i) = sym
sym.infoOrCompleter match {
case info: ClassUnpickler => info.init()
case _ =>
}
readIndex = savedIndex
}
Expand Down Expand Up @@ -493,20 +492,20 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas
}
ctx.newSymbol(owner, name1, flags1, localMemberUnpickler, coord = start)
case CLASSsym =>
val infoRef = readNat()
postReadOp = implicit ctx => atReadPos(index(infoRef), readTypeParams) // force reading type params early, so they get entered in the right order.
var infoRef = readNat()
if (isSymbolRef(infoRef)) infoRef = readNat()
if (isClassRoot)
completeRoot(
classRoot, rootClassUnpickler(start, classRoot.symbol, NoSymbol))
classRoot, rootClassUnpickler(start, classRoot.symbol, NoSymbol, infoRef))
else if (isModuleClassRoot)
completeRoot(
moduleClassRoot, rootClassUnpickler(start, moduleClassRoot.symbol, moduleClassRoot.sourceModule))
moduleClassRoot, rootClassUnpickler(start, moduleClassRoot.symbol, moduleClassRoot.sourceModule, infoRef))
else if (name == tpnme.REFINE_CLASS)
// create a type alias instead
ctx.newSymbol(owner, name, flags, localMemberUnpickler, coord = start)
else {
def completer(cls: Symbol) = {
val unpickler = new LocalUnpickler() withDecls symScope(cls)
val unpickler = new ClassUnpickler(infoRef) withDecls symScope(cls)
if (flags is ModuleClass)
unpickler withSourceModule (implicit ctx =>
cls.owner.info.decls.lookup(cls.name.sourceModuleName)
Expand Down Expand Up @@ -589,8 +588,27 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas

object localMemberUnpickler extends LocalUnpickler

def rootClassUnpickler(start: Coord, cls: Symbol, module: Symbol) =
(new LocalUnpickler with SymbolLoaders.SecondCompleter {
class ClassUnpickler(infoRef: Int) extends LocalUnpickler with TypeParamsCompleter {
private def readTypeParams()(implicit ctx: Context): List[TypeSymbol] = {
val tag = readByte()
val end = readNat() + readIndex
if (tag == POLYtpe) {
val unusedRestperef = readNat()
until(end, readSymbolRef).asInstanceOf[List[TypeSymbol]]
} else Nil
}
private def loadTypeParams(implicit ctx: Context) =
atReadPos(index(infoRef), readTypeParams)

/** Force reading type params early, we need them in setClassInfo of subclasses. */
def init()(implicit ctx: Context) = loadTypeParams

def completerTypeParams(sym: Symbol)(implicit ctx: Context): List[TypeSymbol] =
loadTypeParams
}

def rootClassUnpickler(start: Coord, cls: Symbol, module: Symbol, infoRef: Int) =
(new ClassUnpickler(infoRef) with SymbolLoaders.SecondCompleter {
override def startCoord(denot: SymDenotation): Coord = start
}) withDecls symScope(cls) withSourceModule (_ => module)

Expand Down Expand Up @@ -756,7 +774,7 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas
case POLYtpe =>
val restpe = readTypeRef()
val typeParams = until(end, readSymbolRef)
if (typeParams.nonEmpty) TempPolyType(typeParams, restpe.widenExpr)
if (typeParams.nonEmpty) TempPolyType(typeParams.asInstanceOf[List[TypeSymbol]], restpe.widenExpr)
else ExprType(restpe)
case EXISTENTIALtpe =>
val restpe = readTypeRef()
Expand Down
5 changes: 4 additions & 1 deletion src/dotty/tools/dotc/typer/Checking.scala
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ object Checking {
case SuperType(thistp, _) => isInteresting(thistp)
case AndType(tp1, tp2) => isInteresting(tp1) || isInteresting(tp2)
case OrType(tp1, tp2) => isInteresting(tp1) && isInteresting(tp2)
case _: RefinedOrRecType => true
case _: RefinedOrRecType | _: HKApply => true
case _ => false
}
if (isInteresting(pre)) {
Expand Down Expand Up @@ -223,6 +223,9 @@ object Checking {
val checker = new CheckNonCyclicMap(sym, reportErrors)(ctx.addMode(Mode.CheckCyclic))
try checker.checkInfo(info)
catch {
case ex: AssertionError =>
println(s"assertion error for $info")
throw ex
case ex: CyclicReference =>
if (reportErrors) {
ctx.error(i"illegal cyclic reference: ${checker.where} ${checker.lastChecked} of $sym refers back to the type itself", sym.pos)
Expand Down
57 changes: 30 additions & 27 deletions src/dotty/tools/dotc/typer/Namer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -307,9 +307,14 @@ class Namer { typer: Typer =>
// have no implementation.
val cctx = if (tree.name == nme.CONSTRUCTOR && !(tree.mods is JavaDefined)) ctx.outer else ctx

val completer = tree match {
case tree: TypeDef => new TypeDefCompleter(tree)(cctx)
case _ => new Completer(tree)(cctx)
}

recordSym(ctx.newSymbol(
ctx.owner, name, flags | deferred | method | higherKinded | inSuperCall1,
adjustIfModule(new Completer(tree)(cctx), tree),
adjustIfModule(completer, tree),
privateWithinClass(tree.mods), tree.pos), tree)
case tree: Import =>
recordSym(ctx.newSymbol(
Expand Down Expand Up @@ -489,42 +494,18 @@ class Namer { typer: Typer =>
}

/** The completer of a symbol defined by a member def or import (except ClassSymbols) */
class Completer(val original: Tree)(implicit ctx: Context) extends TypeParamsCompleter {
class Completer(val original: Tree)(implicit ctx: Context) extends LazyType {

protected def localContext(owner: Symbol) = ctx.fresh.setOwner(owner).setTree(original)

private var myTypeParams: List[TypeSymbol] = null
private var nestedCtx: Context = null

def completerTypeParams(sym: Symbol): List[TypeSymbol] = {
if (myTypeParams == null) {
//println(i"completing type params of $sym in ${sym.owner}")
myTypeParams = original match {
case tdef: TypeDef =>
nestedCtx = localContext(sym).setNewScope
locally {
implicit val ctx: Context = nestedCtx
completeParams(tdef.tparams)
tdef.tparams.map(symbolOfTree(_).asType)
}
case _ =>
Nil
}
}
myTypeParams
}

private def typeSig(sym: Symbol): Type = original match {
protected def typeSig(sym: Symbol): Type = original match {
case original: ValDef =>
if (sym is Module) moduleValSig(sym)
else valOrDefDefSig(original, sym, Nil, Nil, identity)(localContext(sym).setNewScope)
case original: DefDef =>
val typer1 = ctx.typer.newLikeThis
nestedTyper(sym) = typer1
typer1.defDefSig(original, sym)(localContext(sym).setTyper(typer1))
case original: TypeDef =>
assert(!original.isClassDef)
typeDefSig(original, sym, completerTypeParams(sym))(nestedCtx)
case imp: Import =>
try {
val expr1 = typedAheadExpr(imp.expr, AnySelectionProto)
Expand Down Expand Up @@ -569,6 +550,28 @@ class Namer { typer: Typer =>
}
}

class TypeDefCompleter(original: TypeDef)(ictx: Context) extends Completer(original)(ictx) with TypeParamsCompleter {
private var myTypeParams: List[TypeSymbol] = null
private var nestedCtx: Context = null
assert(!original.isClassDef)

def completerTypeParams(sym: Symbol)(implicit ctx: Context): List[TypeSymbol] = {
if (myTypeParams == null) {
//println(i"completing type params of $sym in ${sym.owner}")
nestedCtx = localContext(sym).setNewScope
myTypeParams = {
implicit val ctx: Context = nestedCtx
completeParams(original.tparams)
original.tparams.map(symbolOfTree(_).asType)
}
}
myTypeParams
}

override protected def typeSig(sym: Symbol): Type =
typeDefSig(original, sym, completerTypeParams(sym)(ictx))(nestedCtx)
}

class ClassCompleter(cls: ClassSymbol, original: TypeDef)(ictx: Context) extends Completer(original)(ictx) {
withDecls(newScope)

Expand Down