Skip to content

Commit

Permalink
Bring back the restriction for requiring value parameters in poly fun…
Browse files Browse the repository at this point in the history
…ction type definitions
  • Loading branch information
KacperFKorban committed Oct 14, 2024
1 parent c71c71c commit ebe1ceb
Show file tree
Hide file tree
Showing 3 changed files with 13 additions and 38 deletions.
2 changes: 0 additions & 2 deletions compiler/src/dotty/tools/dotc/ast/Desugar.scala
Original file line number Diff line number Diff line change
Expand Up @@ -514,7 +514,6 @@ object desugar {
case Nil =>
params :: Nil

// TODO(kπ) is this enough? SHould this be a TreeTraverse-thing?
def pushDownEvidenceParams(tree: Tree): Tree = tree match
case Function(params, body) =>
cpy.Function(tree)(params, pushDownEvidenceParams(body))
Expand All @@ -527,7 +526,6 @@ object desugar {
makeContextualFunction(paramTpts, paramNames, tree, paramsErased).withSpan(tree.span)

if meth.hasAttachment(PolyFunctionApply) then
// meth.removeAttachment(PolyFunctionApply)
if ctx.mode.is(Mode.Type) then
cpy.DefDef(meth)(tpt = meth.tpt.withAttachment(PolyFunctionApply, params))
else
Expand Down
2 changes: 0 additions & 2 deletions compiler/src/dotty/tools/dotc/parsing/Parsers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1761,8 +1761,6 @@ object Parsers {
getFunction(body) match
case Some(f) =>
PolyFunction(tparams, body)
case None if tparams.exists(_.rhs.isInstanceOf[ContextBounds]) =>
PolyFunction(tparams, body)
case None =>
syntaxError(em"Implementation restriction: polymorphic function types must have a value parameter", arrowOffset)
Ident(nme.ERROR.toTypeName)
Expand Down
47 changes: 13 additions & 34 deletions compiler/src/dotty/tools/dotc/typer/Typer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3588,6 +3588,9 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
}
}

/** Push down the deferred evidence parameters up until the result type is not
* a method type, poly type or a function type
*/
private def pushDownDeferredEvidenceParams(tpe: Type, params: List[untpd.ValDef], span: Span)(using Context): Type = tpe.dealias match {
case tpe: MethodType =>
tpe.derivedLambdaType(tpe.paramNames, tpe.paramInfos, pushDownDeferredEvidenceParams(tpe.resultType, params, span))
Expand All @@ -3609,46 +3612,22 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
typed(ctxFunction).tpe
}

private def extractTopMethodTermParams(tpe: Type)(using Context): (List[TermName], List[Type]) = tpe match {
case tpe: MethodType =>
tpe.paramNames -> tpe.paramInfos
case tpe: RefinedType if defn.isFunctionType(tpe.parent) =>
extractTopMethodTermParams(tpe.refinedInfo)
case _ =>
Nil -> Nil
}

private def removeTopMethodTermParams(tpe: Type)(using Context): Type = tpe match {
case tpe: MethodType =>
tpe.resultType
case tpe: RefinedType if defn.isFunctionType(tpe.parent) =>
tpe.derivedRefinedType(tpe.parent, tpe.refinedName, removeTopMethodTermParams(tpe.refinedInfo))
case tpe: AppliedType if defn.isFunctionType(tpe) =>
tpe.args.last
case _ =>
tpe
}

private def healToPolyFunctionType(tree: Tree)(using Context): Tree = tree match {
case defdef: DefDef if defdef.name == nme.apply && defdef.paramss.forall(_.forall(_.symbol.flags.is(TypeParam))) && defdef.paramss.size == 1 =>
val (names, types) = extractTopMethodTermParams(defdef.tpt.tpe)
val newTpe = removeTopMethodTermParams(defdef.tpt.tpe)
val newParams = names.lazyZip(types).map((name, tpe) => SyntheticValDef(name, TypeTree(tpe), flags = SyntheticTermParam))
val newDefDef = cpy.DefDef(defdef)(paramss = defdef.paramss ++ List(newParams), tpt = untpd.TypeTree(newTpe))
val nestedCtx = ctx.fresh.setNewTyperState()
typed(newDefDef)(using nestedCtx)
case _ => tree
}

/** If the tree has a `PolyFunctionApply` attachment, add the deferred
* evidence parameters as the last argument list before the result type. This
* follows aliases, so the following two types will be expanded to (up to the
* context bound encoding):
* type CmpWeak[X] = X => Boolean
* type Comparer2Weak = [X: Ord] => X => CmpWeak[X]
* ===>
* type CmpWeak[X] = X => Boolean type Comparer2Weak = [X] => X => X ?=>
* Ord[X] => Boolean
*/
private def addDeferredEvidenceParams(tree: Tree, pt: Type)(using Context): (Tree, Type) = {
tree.getAttachment(desugar.PolyFunctionApply) match
case Some(params) if params.nonEmpty =>
tree.removeAttachment(desugar.PolyFunctionApply)
val tpe = pushDownDeferredEvidenceParams(tree.tpe, params, tree.span)
TypeTree(tpe).withSpan(tree.span) -> tpe
// case Some(params) if params.isEmpty =>
// println(s"tree: $tree")
// healToPolyFunctionType(tree) -> pt
case _ => tree -> pt
}

Expand Down

0 comments on commit ebe1ceb

Please sign in to comment.