diff options
author | Martin Odersky <odersky@gmail.com> | 2014-06-18 18:20:14 +0200 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2014-06-18 18:21:07 +0200 |
commit | 7f721438b5bccc8ca9dd68cef273c8cac8199e1a (patch) | |
tree | a619fb770fee578354c7fca1f1c30c68f0d542d0 /src/dotty/tools/dotc/typer | |
parent | 388d9a889c6929699e879a307dc80145b906390a (diff) | |
download | dotty-7f721438b5bccc8ca9dd68cef273c8cac8199e1a.tar.gz dotty-7f721438b5bccc8ca9dd68cef273c8cac8199e1a.tar.bz2 dotty-7f721438b5bccc8ca9dd68cef273c8cac8199e1a.zip |
Handling higher-kinded types with lambdas
Switch to the new scheme where higher-kinded types (and also some polymorphic
type aliases) are represented as instances of Lambda traits.
Diffstat (limited to 'src/dotty/tools/dotc/typer')
-rw-r--r-- | src/dotty/tools/dotc/typer/Applications.scala | 11 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Namer.scala | 29 |
2 files changed, 26 insertions, 14 deletions
diff --git a/src/dotty/tools/dotc/typer/Applications.scala b/src/dotty/tools/dotc/typer/Applications.scala index aaceac0e0..91f4ce9a5 100644 --- a/src/dotty/tools/dotc/typer/Applications.scala +++ b/src/dotty/tools/dotc/typer/Applications.scala @@ -510,10 +510,17 @@ trait Applications extends Compatibility { self: Typer => } def typedTypeApply(tree: untpd.TypeApply, pt: Type)(implicit ctx: Context): Tree = track("typedTypeApply") { - val typedArgs = tree.args mapconserve (typedType(_)) + var typedArgs = tree.args mapconserve (typedType(_)) val typedFn = typedExpr(tree.fun, PolyProto(typedArgs.tpes, pt)) typedFn.tpe.widen match { - case pt: PolyType => checkBounds(typedArgs, pt, tree.pos) + case pt: PolyType => + def adaptTypeArg(tree: tpd.Tree, bound: Type): tpd.Tree = + if (bound.isLambda && !tree.tpe.isLambda && tree.tpe.typeParams.nonEmpty) + tree.withType(tree.tpe.EtaExpand) + else tree + if (typedArgs.length <= pt.paramBounds.length) + typedArgs = typedArgs.zipWithConserve(pt.paramBounds)(adaptTypeArg) + checkBounds(typedArgs, pt, tree.pos) case _ => } assignType(cpy.TypeApply(tree, typedFn, typedArgs), typedFn, typedArgs) diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala index 681523bd2..14404e220 100644 --- a/src/dotty/tools/dotc/typer/Namer.scala +++ b/src/dotty/tools/dotc/typer/Namer.scala @@ -226,8 +226,13 @@ class Namer { typer: Typer => case tree: MemberDef => val name = tree.name.encode checkNoConflict(name) - val deferred = if (lacksDefinition(tree)) Deferred else EmptyFlags + val isDeferred = lacksDefinition(tree) + val deferred = if (isDeferred) Deferred else EmptyFlags val method = if (tree.isInstanceOf[DefDef]) Method else EmptyFlags + val higherKinded = tree match { + case tree: TypeDef if tree.tparams.nonEmpty && isDeferred => HigherKinded + case _ => EmptyFlags + } // to complete a constructor, move one context further out -- this // is the context enclosing the class. Note that the context in which a @@ -238,7 +243,7 @@ class Namer { typer: Typer => val cctx = if (tree.name == nme.CONSTRUCTOR) ctx.outer else ctx record(ctx.newSymbol( - ctx.owner, name, tree.mods.flags | deferred | method, + ctx.owner, name, tree.mods.flags | deferred | method | higherKinded, adjustIfModule(new Completer(tree)(cctx), tree), privateWithinClass(tree.mods), tree.pos)) case tree: Import => @@ -453,7 +458,7 @@ class Namer { typer: Typer => val Select(New(tpt), nme.CONSTRUCTOR) = core val targs1 = targs map (typedAheadType(_)) val ptype = typedAheadType(tpt).tpe appliedTo targs1.tpes - if (ptype.uninstantiatedTypeParams.isEmpty) ptype + if (ptype.typeParams.isEmpty) ptype else typedAheadExpr(parent).tpe } @@ -661,17 +666,17 @@ class Namer { typer: Typer => completeParams(tdef.tparams) sym.info = TypeBounds.empty // avoid cyclic reference errors for F-bounds val tparamSyms = tdef.tparams map symbolOfTree + val isDerived = tdef.rhs.isInstanceOf[untpd.DerivedTypeTree] + val toParameterize = tparamSyms.nonEmpty && !isDerived + val needsLambda = sym.allOverriddenSymbols.exists(_ is HigherKinded) && !isDerived val rhsType = typedAheadType(tdef.rhs).tpe - + def abstractedRhsType = + if (needsLambda) rhsType.LambdaAbstract(tparamSyms) + else if (toParameterize) rhsType.parameterizeWith(tparamSyms) + else rhsType rhsType match { - case bounds: TypeBounds => - if (tparamSyms.nonEmpty) bounds.higherKinded(tparamSyms) - else rhsType - case _ => - val abstractedRhsType = - if (tparamSyms.nonEmpty) rhsType.LambdaAbstract(tparamSyms)(ctx.error(_, _)) - else rhsType - TypeAlias(abstractedRhsType, if (sym is Local) sym.variance else 0) + case _: TypeBounds => abstractedRhsType + case _ => TypeAlias(abstractedRhsType, if (sym is Local) sym.variance else 0) } } }
\ No newline at end of file |