Skip to content

Commit 3eeadfd

Browse files
committed
Add defn.FunctionNOf
1 parent 25d26b1 commit 3eeadfd

File tree

9 files changed

+42
-18
lines changed

9 files changed

+42
-18
lines changed

compiler/src/dotty/tools/dotc/core/Definitions.scala

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1109,23 +1109,47 @@ class Definitions {
11091109
sym.owner.linkedClass.typeRef
11101110

11111111
object FunctionOf {
1112+
/** Create a `FunctionN`, `ContextFunctionN` or refined `PolyFunction` type applied to the arguments and result type
1113+
*
1114+
* `PolyFunction` is used if at least one of the arguments is annotated as erased.
1115+
*/
11121116
def apply(args: List[Type], resultType: Type, isContextual: Boolean = false)(using Context): Type =
11131117
val mt = MethodType.companion(isContextual, false)(args, resultType)
11141118
if mt.hasErasedParams then
11151119
RefinedType(PolyFunctionClass.typeRef, nme.apply, mt)
11161120
else
1117-
FunctionType(args.length, isContextual).appliedTo(args ::: resultType :: Nil)
1121+
FunctionNOf(args, resultType, isContextual)
1122+
1123+
/** Matches a (possibly aliased) `FunctionN[...]`, `ContextFunctionN[...]` or refined `PolyFunction`.
1124+
* Extracts the list of function argument types, the result type and whether function is contextual.
1125+
*/
11181126
def unapply(ft: Type)(using Context): Option[(List[Type], Type, Boolean)] = {
11191127
ft.dealias match
11201128
case PolyFunctionOf(mt: MethodType) =>
11211129
Some(mt.paramInfos, mt.resType, mt.isContextualMethod)
1122-
case dft =>
1123-
val tsym = dft.typeSymbol
1124-
if isFunctionSymbol(tsym) && ft.isRef(tsym) then
1125-
val targs = dft.argInfos
1126-
if (targs.isEmpty) None
1127-
else Some(targs.init, targs.last, tsym.name.isContextFunction)
1128-
else None
1130+
case FunctionNOf(targs, resType, isContextual) =>
1131+
Some(targs, resType, isContextual)
1132+
case _ =>
1133+
None
1134+
}
1135+
}
1136+
1137+
object FunctionNOf {
1138+
/** Create a `FunctionN` or `ContextFunctionN` type applied to the arguments and result type */
1139+
def apply(args: List[Type], resultType: Type, isContextual: Boolean = false)(using Context): Type =
1140+
FunctionType(args.length, isContextual).appliedTo(args ::: resultType :: Nil)
1141+
1142+
/** Matches a (possibly aliased) `FunctionN[...]` or `ContextFunctionN[...]`.
1143+
* Extracts the list of function argument types, the result type and whether function is contextual.
1144+
*/
1145+
def unapply(ft: Type)(using Context): Option[(List[Type], Type, Boolean)] = {
1146+
val dft = ft.dealias
1147+
val tsym = dft.typeSymbol
1148+
if isFunctionSymbol(tsym) && ft.isRef(tsym) then
1149+
val targs = dft.argInfos
1150+
if (targs.isEmpty) None
1151+
else Some(targs.init, targs.last, tsym.name.isContextFunction)
1152+
else None
11291153
}
11301154
}
11311155

compiler/src/dotty/tools/dotc/core/TypeErasure.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -933,7 +933,7 @@ class TypeErasure(sourceLanguage: SourceLanguage, semiEraseVCs: Boolean, isConst
933933
case tp: TermRef =>
934934
sigName(underlyingOfTermRef(tp))
935935
case ExprType(rt) =>
936-
sigName(defn.FunctionOf(Nil, rt))
936+
sigName(defn.FunctionNOf(Nil, rt))
937937
case tp: TypeVar if !tp.isInstantiated =>
938938
tpnme.Uninstantiated
939939
case tp @ defn.PolyFunctionOf(_) =>

compiler/src/dotty/tools/dotc/core/Types.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1882,7 +1882,7 @@ object Types {
18821882
case res: MethodType => res.toFunctionType(isJava)
18831883
case res => res
18841884
}
1885-
defn.FunctionOf(
1885+
defn.FunctionNOf(
18861886
formals1 mapConserve (_.translateFromRepeated(toArray = isJava)),
18871887
result1, isContextual)
18881888
if mt.hasErasedParams then

compiler/src/dotty/tools/dotc/transform/PickleQuotes.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,7 @@ object PickleQuotes {
326326
defn.QuotedExprClass.typeRef.appliedTo(defn.AnyType)),
327327
args =>
328328
val cases = holeContents.zipWithIndex.map { case (splice, idx) =>
329-
val defn.FunctionOf(argTypes, defn.FunctionOf(quotesType :: _, _, _), _) = splice.tpe: @unchecked
329+
val defn.FunctionNOf(argTypes, defn.FunctionNOf(quotesType :: _, _, _), _) = splice.tpe: @unchecked
330330
val rhs = {
331331
val spliceArgs = argTypes.zipWithIndex.map { (argType, i) =>
332332
args(1).select(nme.apply).appliedTo(Literal(Constant(i))).asInstance(argType)

compiler/src/dotty/tools/dotc/transform/SpecializeFunctions.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ class SpecializeFunctions extends MiniPhase {
8888
// Need to cast to regular function, since specialized apply methods
8989
// are not members of ContextFunction0. The cast will be eliminated in
9090
// erasure.
91-
qual.cast(defn.FunctionOf(Nil, res))
91+
qual.cast(defn.FunctionNOf(Nil, res))
9292
case _ =>
9393
qual
9494
qual1.select(specializedApply)

compiler/src/dotty/tools/dotc/transform/TreeChecker.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -749,9 +749,9 @@ object TreeChecker {
749749
if isTerm then defn.QuotedExprClass.typeRef.appliedTo(tree1.typeOpt)
750750
else defn.QuotedTypeClass.typeRef.appliedTo(tree1.typeOpt)
751751
val contextualResult =
752-
defn.FunctionOf(List(defn.QuotesClass.typeRef), expectedResultType, isContextual = true)
752+
defn.FunctionNOf(List(defn.QuotesClass.typeRef), expectedResultType, isContextual = true)
753753
val expectedContentType =
754-
defn.FunctionOf(argQuotedTypes, contextualResult)
754+
defn.FunctionNOf(argQuotedTypes, contextualResult)
755755
assert(content.typeOpt =:= expectedContentType, i"unexpected content of hole\nexpected: ${expectedContentType}\nwas: ${content.typeOpt}")
756756

757757
tree1

compiler/src/dotty/tools/dotc/typer/Applications.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1934,7 +1934,7 @@ trait Applications extends Compatibility {
19341934
/** The shape of given tree as a type; cannot handle named arguments. */
19351935
def typeShape(tree: untpd.Tree): Type = tree match {
19361936
case untpd.Function(args, body) =>
1937-
defn.FunctionOf(
1937+
defn.FunctionNOf(
19381938
args.map(Function.const(defn.AnyType)), typeShape(body),
19391939
isContextual = untpd.isContextualClosure(tree))
19401940
case Match(EmptyTree, _) =>

compiler/src/dotty/tools/dotc/typer/QuotesAndSplices.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ trait QuotesAndSplices {
122122
for arg <- typedArgs if arg.symbol.is(Mutable) do // TODO support these patterns. Possibly using scala.quoted.util.Var
123123
report.error("References to `var`s cannot be used in higher-order pattern", arg.srcPos)
124124
val argTypes = typedArgs.map(_.tpe.widenTermRefExpr)
125-
val patType = if tree.args.isEmpty then pt else defn.FunctionOf(argTypes, pt)
125+
val patType = if tree.args.isEmpty then pt else defn.FunctionNOf(argTypes, pt)
126126
val pat = typedPattern(tree.body, defn.QuotedExprClass.typeRef.appliedTo(patType))(using quotePatternSpliceContext)
127127
val baseType = pat.tpe.baseType(defn.QuotedExprClass)
128128
val argType = if baseType.exists then baseType.argTypesHi.head else defn.NothingType
@@ -148,7 +148,7 @@ trait QuotesAndSplices {
148148
if isInBraces then // ${x}(...) match an application
149149
val typedArgs = args.map(arg => typedExpr(arg))
150150
val argTypes = typedArgs.map(_.tpe.widenTermRefExpr)
151-
val splice1 = typedSplicePattern(splice, defn.FunctionOf(argTypes, pt))
151+
val splice1 = typedSplicePattern(splice, defn.FunctionNOf(argTypes, pt))
152152
untpd.cpy.Apply(tree)(splice1.select(nme.apply), typedArgs).withType(pt)
153153
else // $x(...) higher-order quasipattern
154154
if args.isEmpty then

compiler/src/dotty/tools/dotc/typer/Synthesizer.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
102102
case AppliedType(_, funArgs @ fun :: tupled :: Nil) =>
103103
def functionTypeEqual(baseFun: Type, actualArgs: List[Type],
104104
actualRet: Type, expected: Type) =
105-
expected =:= defn.FunctionOf(actualArgs, actualRet,
105+
expected =:= defn.FunctionNOf(actualArgs, actualRet,
106106
defn.isContextFunctionType(baseFun))
107107
val arity: Int =
108108
if defn.isFunctionNType(fun) then

0 commit comments

Comments
 (0)