Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add defn.FunctionNOf.{apply,unapply} #18418

Merged
merged 3 commits into from
Nov 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/cc/Synthetics.scala
Original file line number Diff line number Diff line change
Expand Up @@ -174,9 +174,9 @@ object Synthetics:
val (et: ExprType) = symd.info: @unchecked
val (enclThis: ThisType) = symd.owner.thisType: @unchecked
def mapFinalResult(tp: Type, f: Type => Type): Type =
val defn.FunctionOf(args, res, isContextual) = tp: @unchecked
val defn.FunctionNOf(args, res, isContextual) = tp: @unchecked
if defn.isFunctionNType(res) then
defn.FunctionOf(args, mapFinalResult(res, f), isContextual)
defn.FunctionNOf(args, mapFinalResult(res, f), isContextual)
else
f(tp)
val resType1 =
Expand Down
21 changes: 17 additions & 4 deletions compiler/src/dotty/tools/dotc/core/Definitions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1111,10 +1111,9 @@ 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(PolyFunctionClass.typeRef, nme.apply, mt)
else
FunctionType(args.length, isContextual).appliedTo(args ::: resultType :: Nil)
if mt.hasErasedParams then RefinedType(PolyFunctionClass.typeRef, nme.apply, mt)
else FunctionNOf(args, resultType, isContextual)

def unapply(ft: Type)(using Context): Option[(List[Type], Type, Boolean)] = {
ft.dealias match
case PolyFunctionOf(mt: MethodType) =>
Expand All @@ -1129,6 +1128,20 @@ class Definitions {
}
}

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 @@ -933,7 +933,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.PolyFunctionOf(_) =>
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 @@ -1890,7 +1890,7 @@ object Types {
case res: MethodType => res.toFunctionType(isJava)
case res => res
}
defn.FunctionOf(
defn.FunctionNOf(
mt.paramInfos.mapConserve(_.translateFromRepeated(toArray = isJava)),
result1, isContextual)
if mt.hasErasedParams 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 @@ -749,9 +749,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 @@ -1724,7 +1724,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 @@ -1951,7 +1951,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 @@ -1991,8 +1991,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 @@ -2077,8 +2077,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 @@ -2266,7 +2266,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 @@ -383,9 +383,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 @@ -424,7 +424,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 @@ -122,7 +122,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 quotePatternSpliceContext)
val baseType = pat.tpe.baseType(defn.QuotedExprClass)
val argType = if baseType.exists then baseType.argTypesHi.head else defn.NothingType
Expand All @@ -148,7 +148,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 @@ -105,7 +105,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 defn.isFunctionNType(fun) then
Expand Down
Loading