diff --git a/src/dotty/tools/dotc/core/TypeApplications.scala b/src/dotty/tools/dotc/core/TypeApplications.scala index 661975dabce9..40cbb92e7786 100644 --- a/src/dotty/tools/dotc/core/TypeApplications.scala +++ b/src/dotty/tools/dotc/core/TypeApplications.scala @@ -16,6 +16,8 @@ import util.Positions.Position import config.Printers._ import collection.mutable import java.util.NoSuchElementException +import ast.untpd.TypeDef +import typer.Namer object TypeApplications { @@ -63,7 +65,14 @@ class TypeApplications(val self: Type) extends AnyVal { case self: TypeRef => val tsym = self.typeSymbol if (tsym.isClass) tsym.typeParams - else if (tsym.isAliasType) self.underlying.typeParams + else if (tsym.isAliasType) { + tsym.infoOrCompleter match { + case c: Namer#Completer => + c.typeParams(tsym) + case _ => + self.underlying.typeParams + } + } else { val lam = LambdaClass(forcing = false) if (lam.exists) lam.typeParams else Nil @@ -200,6 +209,13 @@ class TypeApplications(val self: Type) extends AnyVal { case nil => tp } + def canForce(sym: Symbol) = sym.infoOrCompleter match { + case c: Namer#Completer => + !sym.isAliasType + case _ => + true + } + /** Instantiate type `tp` with `args`. * @param original The original type for which we compute the type parameters * This makes a difference for refinement types, because @@ -209,7 +225,7 @@ class TypeApplications(val self: Type) extends AnyVal { def instantiate(tp: Type, original: Type): Type = tp match { case tp: TypeRef => val tsym = tp.symbol - if (tsym.isAliasType) tp.underlying.appliedTo(args) + if (tsym.isAliasType && canForce(tsym)) tp.underlying.appliedTo(args) else { val safeTypeParams = if (tsym.isClass || !tp.typeSymbol.isCompleting) original.typeParams @@ -242,7 +258,7 @@ class TypeApplications(val self: Type) extends AnyVal { case tp: TypeRef => val sym = tp.symbol if (sym.isClass) sym.isLambdaTrait - else !sym.isAliasType || isKnownHK(tp.info) + else !sym.isAliasType || !canForce(sym) || isKnownHK(tp.info) case tp: TypeProxy => isKnownHK(tp.underlying) case _ => false } diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala index 5eebdbad1cc8..491b7fbe6238 100644 --- a/src/dotty/tools/dotc/typer/Namer.scala +++ b/src/dotty/tools/dotc/typer/Namer.scala @@ -478,6 +478,8 @@ 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 LazyType { + var completedParams: Boolean = false + var nestedCtx: Context = null protected def localContext(owner: Symbol) = ctx.fresh.setOwner(owner).setTree(original) @@ -491,7 +493,9 @@ class Namer { typer: Typer => typer1.defDefSig(original, sym)(localContext(sym).setTyper(typer1)) case original: TypeDef => assert(!original.isClassDef) - typeDefSig(original, sym)(localContext(sym).setNewScope) + if (nestedCtx == null) + nestedCtx = localContext(sym).setNewScope + typeDefSig(original, sym, completedParams)(nestedCtx) case imp: Import => try { val expr1 = typedAheadExpr(imp.expr, AnySelectionProto) @@ -503,6 +507,21 @@ class Namer { typer: Typer => } } + def typeParams(sym: Symbol) = original match { + case tdef: TypeDef => + if (nestedCtx == null) + nestedCtx = localContext(sym).setNewScope + + { + implicit val ctx: Context = nestedCtx + if (!completedParams) { + completeParams(tdef.tparams) + completedParams = true + } + tdef.tparams map (symbolOfTree(_).asType) + } + } + final override def complete(denot: SymDenotation)(implicit ctx: Context) = { if (completions != noPrinter && ctx.typerState != this.ctx.typerState) { completions.println(completions.getClass.toString) @@ -807,8 +826,9 @@ class Namer { typer: Typer => else valOrDefDefSig(ddef, sym, typeParams, paramSymss, wrapMethType) } - def typeDefSig(tdef: TypeDef, sym: Symbol)(implicit ctx: Context): Type = { - completeParams(tdef.tparams) + def typeDefSig(tdef: TypeDef, sym: Symbol, completedParams: Boolean)(implicit ctx: Context): Type = { + if (!completedParams) + completeParams(tdef.tparams) val tparamSyms = tdef.tparams map symbolOfTree val isDerived = tdef.rhs.isInstanceOf[untpd.DerivedTypeTree] //val toParameterize = tparamSyms.nonEmpty && !isDerived