diff options
author | Martin Odersky <odersky@gmail.com> | 2016-04-07 17:58:52 +0200 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2016-04-07 17:59:27 +0200 |
commit | 03e8c54c0165d129b12bdde29b2482dd1758e418 (patch) | |
tree | ddca733ac77e4c19a4465788c54302bdccb9e7e9 /src | |
parent | 306d422f1e3017731d1f9266f9d445e77ea73105 (diff) | |
download | dotty-03e8c54c0165d129b12bdde29b2482dd1758e418.tar.gz dotty-03e8c54c0165d129b12bdde29b2482dd1758e418.tar.bz2 dotty-03e8c54c0165d129b12bdde29b2482dd1758e418.zip |
Treat type parameters of secondary constructors as aliases
... of class parameters using the gadt mechanism. Previously they were encoded as aliases
by hardcoding alias bounds in the type parameter declaration, but that then leads to
weird behavior and failures in unpickling.
To make this work, we also need to propagate gadt bounds into the this-call context.
Test case in pickling/i1202a.scala.
Diffstat (limited to 'src')
-rw-r--r-- | src/dotty/tools/dotc/core/Contexts.scala | 11 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Typer.scala | 19 |
2 files changed, 19 insertions, 11 deletions
diff --git a/src/dotty/tools/dotc/core/Contexts.scala b/src/dotty/tools/dotc/core/Contexts.scala index a0bb03e50..53a4bfe08 100644 --- a/src/dotty/tools/dotc/core/Contexts.scala +++ b/src/dotty/tools/dotc/core/Contexts.scala @@ -336,13 +336,17 @@ object Contexts { def thisCallArgContext: Context = { assert(owner.isClassConstructor) val constrCtx = outersIterator.dropWhile(_.outer.owner == owner).next - superOrThisCallContext(owner, constrCtx.scope).setTyperState(typerState) + superOrThisCallContext(owner, constrCtx.scope) + .setTyperState(typerState) + .setGadt(gadt) } - /** The super= or this-call context with given owner and locals. */ + /** The super- or this-call context with given owner and locals. */ private def superOrThisCallContext(owner: Symbol, locals: Scope): FreshContext = { var classCtx = outersIterator.dropWhile(!_.isClassDefContext).next - classCtx.outer.fresh.setOwner(owner).setScope(locals).setMode(classCtx.mode | Mode.InSuperCall) + classCtx.outer.fresh.setOwner(owner) + .setScope(locals) + .setMode(classCtx.mode | Mode.InSuperCall) } /** The context of expression `expr` seen as a member of a statement sequence */ @@ -438,6 +442,7 @@ object Contexts { def setImportInfo(importInfo: ImportInfo): this.type = { this.importInfo = importInfo; this } def setRunInfo(runInfo: RunInfo): this.type = { this.runInfo = runInfo; this } def setDiagnostics(diagnostics: Option[StringBuilder]): this.type = { this.diagnostics = diagnostics; this } + def setGadt(gadt: GADTMap): this.type = { this.gadt = gadt; this } def setTypeComparerFn(tcfn: Context => TypeComparer): this.type = { this.typeComparer = tcfn(this); this } def setSearchHistory(searchHistory: SearchHistory): this.type = { this.searchHistory = searchHistory; this } def setFreshNames(freshNames: FreshNameCreator): this.type = { this.freshNames = freshNames; this } diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala index 3d36905f2..10d7516e6 100644 --- a/src/dotty/tools/dotc/typer/Typer.scala +++ b/src/dotty/tools/dotc/typer/Typer.scala @@ -1022,17 +1022,20 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit val DefDef(name, tparams, vparamss, tpt, _) = ddef completeAnnotations(ddef, sym) val tparams1 = tparams mapconserve (typed(_).asInstanceOf[TypeDef]) - // for secondary constructors we need to use that their type parameters - // are aliases of the class type parameters. See pos/i941.scala - if (sym.isConstructor && !sym.isPrimaryConstructor) - (sym.owner.typeParams, tparams1).zipped.foreach {(tparam, tdef) => - tdef.symbol.info = TypeAlias(tparam.typeRef) - } - val vparamss1 = vparamss nestedMapconserve (typed(_).asInstanceOf[ValDef]) if (sym is Implicit) checkImplicitParamsNotSingletons(vparamss1) val tpt1 = checkSimpleKinded(typedType(tpt)) - val rhs1 = typedExpr(ddef.rhs, tpt1.tpe) + + var rhsCtx = ctx + if (sym.isConstructor && !sym.isPrimaryConstructor && tparams1.nonEmpty) { + // for secondary constructors we need a context that "knows" + // that their type parameters are aliases of the class type parameters. + // See pos/i941.scala + rhsCtx = ctx.fresh.setFreshGADTBounds + (tparams1, sym.owner.typeParams).zipped.foreach ((tdef, tparam) => + rhsCtx.gadt.setBounds(tdef.symbol, TypeAlias(tparam.typeRef))) + } + val rhs1 = typedExpr(ddef.rhs, tpt1.tpe)(rhsCtx) assignType(cpy.DefDef(ddef)(name, tparams1, vparamss1, tpt1, rhs1), sym) //todo: make sure dependent method types do not depend on implicits or by-name params } |