Skip to content

Commit

Permalink
Backport "Add defn.FunctionNOf.{apply,unapply}" to LTS (#20773)
Browse files Browse the repository at this point in the history
Backports #18418 to the LTS branch.

PR submitted by the release tooling.
[skip ci]
  • Loading branch information
WojciechMazur authored Jun 26, 2024
2 parents 53eeabf + 719fdd9 commit 708ac63
Show file tree
Hide file tree
Showing 10 changed files with 35 additions and 23 deletions.
20 changes: 16 additions & 4 deletions compiler/src/dotty/tools/dotc/core/Definitions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1102,10 +1102,8 @@ class Definitions {
object FunctionOf {
def apply(args: List[Type], resultType: Type, isContextual: Boolean = false)(using Context): Type =
val mt = MethodType.companion(isContextual, false)(args, resultType)
if mt.hasErasedParams then
RefinedType(ErasedFunctionClass.typeRef, nme.apply, mt)
else
FunctionType(args.length, isContextual).appliedTo(args ::: resultType :: Nil)
if mt.hasErasedParams then RefinedType(ErasedFunctionClass.typeRef, nme.apply, mt)
else FunctionNOf(args, resultType, isContextual)
def unapply(ft: Type)(using Context): Option[(List[Type], Type, Boolean)] = {
ft.dealias match
case ErasedFunctionOf(mt) =>
Expand All @@ -1132,6 +1130,20 @@ class Definitions {
case _ => None
}

object FunctionNOf {
/** Create a `FunctionN` or `ContextFunctionN` type applied to the arguments and result type */
def apply(args: List[Type], resultType: Type, isContextual: Boolean = false)(using Context): Type =
FunctionType(args.length, isContextual).appliedTo(args ::: resultType :: Nil)

/** Matches a (possibly aliased) `FunctionN[...]` or `ContextFunctionN[...]`.
* Extracts the list of function argument types, the result type and whether function is contextual.
*/
def unapply(tpe: AppliedType)(using Context): Option[(List[Type], Type, Boolean)] = {
if !isFunctionNType(tpe) then None
else Some(tpe.args.init, tpe.args.last, tpe.typeSymbol.name.isContextFunction)
}
}

object RefinedFunctionOf {
/** Matches a refined `PolyFunction`/`FunctionN[...]`/`ContextFunctionN[...]`.
* Extracts the method type type and apply info.
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/core/TypeErasure.scala
Original file line number Diff line number Diff line change
Expand Up @@ -932,7 +932,7 @@ class TypeErasure(sourceLanguage: SourceLanguage, semiEraseVCs: Boolean, isConst
case tp: TermRef =>
sigName(underlyingOfTermRef(tp))
case ExprType(rt) =>
sigName(defn.FunctionOf(Nil, rt))
sigName(defn.FunctionNOf(Nil, rt))
case tp: TypeVar if !tp.isInstantiated =>
tpnme.Uninstantiated
case tp @ defn.PolyOrErasedFunctionOf(_) =>
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/core/Types.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1874,7 +1874,7 @@ object Types {
case res: MethodType => res.toFunctionType(isJava)
case res => res
}
val funType = defn.FunctionOf(
val funType = defn.FunctionNOf(
mt.paramInfos.mapConserve(_.translateFromRepeated(toArray = isJava)),
result1, isContextual)
if alwaysDependent || mt.isResultDependent then
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/transform/PickleQuotes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ object PickleQuotes {
defn.QuotedExprClass.typeRef.appliedTo(defn.AnyType)),
args =>
val cases = holeContents.zipWithIndex.map { case (splice, idx) =>
val defn.FunctionOf(argTypes, defn.FunctionOf(quotesType :: _, _, _), _) = splice.tpe: @unchecked
val defn.FunctionNOf(argTypes, defn.FunctionNOf(quotesType :: _, _, _), _) = splice.tpe: @unchecked
val rhs = {
val spliceArgs = argTypes.zipWithIndex.map { (argType, i) =>
args(1).select(nme.apply).appliedTo(Literal(Constant(i))).asInstance(argType)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ class SpecializeFunctions extends MiniPhase {
// Need to cast to regular function, since specialized apply methods
// are not members of ContextFunction0. The cast will be eliminated in
// erasure.
qual.cast(defn.FunctionOf(Nil, res))
qual.cast(defn.FunctionNOf(Nil, res))
case _ =>
qual
qual1.select(specializedApply)
Expand Down
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/transform/TreeChecker.scala
Original file line number Diff line number Diff line change
Expand Up @@ -728,9 +728,9 @@ object TreeChecker {
if isTerm then defn.QuotedExprClass.typeRef.appliedTo(tree1.typeOpt)
else defn.QuotedTypeClass.typeRef.appliedTo(tree1.typeOpt)
val contextualResult =
defn.FunctionOf(List(defn.QuotesClass.typeRef), expectedResultType, isContextual = true)
defn.FunctionNOf(List(defn.QuotesClass.typeRef), expectedResultType, isContextual = true)
val expectedContentType =
defn.FunctionOf(argQuotedTypes, contextualResult)
defn.FunctionNOf(argQuotedTypes, contextualResult)
assert(content.typeOpt =:= expectedContentType, i"unexpected content of hole\nexpected: ${expectedContentType}\nwas: ${content.typeOpt}")

tree1
Expand Down
14 changes: 7 additions & 7 deletions compiler/src/dotty/tools/dotc/typer/Applications.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1717,7 +1717,7 @@ trait Applications extends Compatibility {
def apply(t: Type) = t match {
case t @ AppliedType(tycon, args) =>
def mapArg(arg: Type, tparam: TypeParamInfo) =
if (variance > 0 && tparam.paramVarianceSign < 0) defn.FunctionOf(arg :: Nil, defn.UnitType)
if (variance > 0 && tparam.paramVarianceSign < 0) defn.FunctionNOf(arg :: Nil, defn.UnitType)
else arg
mapOver(t.derivedAppliedType(tycon, args.zipWithConserve(tycon.typeParams)(mapArg)))
case _ => mapOver(t)
Expand Down Expand Up @@ -1944,7 +1944,7 @@ trait Applications extends Compatibility {
/** The shape of given tree as a type; cannot handle named arguments. */
def typeShape(tree: untpd.Tree): Type = tree match {
case untpd.Function(args, body) =>
defn.FunctionOf(
defn.FunctionNOf(
args.map(Function.const(defn.AnyType)), typeShape(body),
isContextual = untpd.isContextualClosure(tree))
case Match(EmptyTree, _) =>
Expand Down Expand Up @@ -1984,8 +1984,8 @@ trait Applications extends Compatibility {
def paramCount(ref: TermRef) =
val formals = ref.widen.firstParamTypes
if formals.length > idx then
formals(idx) match
case defn.FunctionOf(args, _, _) => args.length
formals(idx).dealias match
case defn.FunctionNOf(args, _, _) => args.length
case _ => -1
else -1

Expand Down Expand Up @@ -2070,8 +2070,8 @@ trait Applications extends Compatibility {
else resolveMapped(alts1, _.widen.appliedTo(targs1.tpes), pt1)

case pt =>
val compat0 = pt match
case defn.FunctionOf(args, resType, _) =>
val compat0 = pt.dealias match
case defn.FunctionNOf(args, resType, _) =>
narrowByTypes(alts, args, resType)
case _ =>
Nil
Expand Down Expand Up @@ -2260,7 +2260,7 @@ trait Applications extends Compatibility {
false
val commonFormal =
if (isPartial) defn.PartialFunctionOf(commonParamTypes.head, WildcardType)
else defn.FunctionOf(commonParamTypes, WildcardType, isContextual = untpd.isContextualClosure(arg))
else defn.FunctionNOf(commonParamTypes, WildcardType, isContextual = untpd.isContextualClosure(arg))
overload.println(i"pretype arg $arg with expected type $commonFormal")
if (commonParamTypes.forall(isFullyDefined(_, ForceDegree.flipBottom)))
withMode(Mode.ImplicitsEnabled) {
Expand Down
6 changes: 3 additions & 3 deletions compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -371,9 +371,9 @@ object ProtoTypes {
def allArgTypesAreCurrent()(using Context): Boolean =
state.typedArg.size == args.length

private def isUndefined(tp: Type): Boolean = tp match {
private def isUndefined(tp: Type): Boolean = tp.dealias match {
case _: WildcardType => true
case defn.FunctionOf(args, result, _) => args.exists(isUndefined) || isUndefined(result)
case defn.FunctionNOf(args, result, _) => args.exists(isUndefined) || isUndefined(result)
case _ => false
}

Expand Down Expand Up @@ -412,7 +412,7 @@ object ProtoTypes {
case ValDef(_, tpt, _) if !tpt.isEmpty => typer.typedType(tpt).typeOpt
case _ => WildcardType
}
targ = arg.withType(defn.FunctionOf(paramTypes, WildcardType))
targ = arg.withType(defn.FunctionNOf(paramTypes, WildcardType))
case Some(_) if !force =>
targ = arg.withType(WildcardType)
case _ =>
Expand Down
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/typer/QuotesAndSplices.scala
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ trait QuotesAndSplices {
for arg <- typedArgs if arg.symbol.is(Mutable) do // TODO support these patterns. Possibly using scala.quoted.util.Var
report.error("References to `var`s cannot be used in higher-order pattern", arg.srcPos)
val argTypes = typedArgs.map(_.tpe.widenTermRefExpr)
val patType = if tree.args.isEmpty then pt else defn.FunctionOf(argTypes, pt)
val patType = if tree.args.isEmpty then pt else defn.FunctionNOf(argTypes, pt)
val pat = typedPattern(tree.body, defn.QuotedExprClass.typeRef.appliedTo(patType))(
using spliceContext.retractMode(Mode.QuotedPattern).addMode(Mode.Pattern).withOwner(patternOuterContext(ctx).owner))
val baseType = pat.tpe.baseType(defn.QuotedExprClass)
Expand All @@ -143,7 +143,7 @@ trait QuotesAndSplices {
if isInBraces then // ${x}(...) match an application
val typedArgs = args.map(arg => typedExpr(arg))
val argTypes = typedArgs.map(_.tpe.widenTermRefExpr)
val splice1 = typedSplicePattern(splice, defn.FunctionOf(argTypes, pt))
val splice1 = typedSplicePattern(splice, defn.FunctionNOf(argTypes, pt))
untpd.cpy.Apply(tree)(splice1.select(nme.apply), typedArgs).withType(pt)
else // $x(...) higher-order quasipattern
if args.isEmpty then
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/typer/Synthesizer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
case AppliedType(_, funArgs @ fun :: tupled :: Nil) =>
def functionTypeEqual(baseFun: Type, actualArgs: List[Type],
actualRet: Type, expected: Type) =
expected =:= defn.FunctionOf(actualArgs, actualRet,
expected =:= defn.FunctionNOf(actualArgs, actualRet,
defn.isContextFunctionType(baseFun))
val arity: Int =
if fun.derivesFrom(defn.ErasedFunctionClass) then -1 // TODO support?
Expand Down

0 comments on commit 708ac63

Please sign in to comment.