From ebe1cebd1c0d95e4be27992a0db495e372ccb31b Mon Sep 17 00:00:00 2001 From: Kacper Korban Date: Mon, 14 Oct 2024 12:18:25 +0200 Subject: [PATCH] Bring back the restriction for requiring value parameters in poly function type definitions --- .../src/dotty/tools/dotc/ast/Desugar.scala | 2 - .../dotty/tools/dotc/parsing/Parsers.scala | 2 - .../src/dotty/tools/dotc/typer/Typer.scala | 47 +++++-------------- 3 files changed, 13 insertions(+), 38 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index 5b3cc9b04049..8a2dd40399c1 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -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)) @@ -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 diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index adef5bd5717b..f51d4ffd3bc7 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -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) diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 137bd8d7be8a..90181c885c7d 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -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)) @@ -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 }