Skip to content

Commit 5cb78bb

Browse files
committed
Refine isFunctionType
`isFunctionType` nor returns true for dependent as well as non-dependent function types. `isNonDepFunctionType` returns true only for the latter.
1 parent e013788 commit 5cb78bb

File tree

4 files changed

+22
-14
lines changed

4 files changed

+22
-14
lines changed

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

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -915,17 +915,18 @@ class Definitions {
915915
def isProductSubType(tp: Type)(implicit ctx: Context) =
916916
tp.derivesFrom(ProductType.symbol)
917917

918-
/** Is `tp` (an alias) of either a scala.FunctionN or a scala.ImplicitFunctionN? */
919-
def isFunctionType(tp: Type)(implicit ctx: Context) = {
918+
/** Is `tp` (an alias) of either a scala.FunctionN or a scala.ImplicitFunctionN
919+
* instance?
920+
*/
921+
def isNonDepFunctionType(tp: Type)(implicit ctx: Context) = {
920922
val arity = functionArity(tp)
921923
val sym = tp.dealias.typeSymbol
922924
arity >= 0 && isFunctionClass(sym) && tp.isRef(FunctionType(arity, sym.name.isImplicitFunction).typeSymbol)
923925
}
924926

925-
def isDependentFunctionType(tp: Type)(implicit ctx: Context) = tp.stripTypeVar match {
926-
case RefinedType(parent, nme.apply, _) => isFunctionType(parent)
927-
case _ => false
928-
}
927+
/** Is `tp` a representation of a (possibly depenent) function type or an alias of such? */
928+
def isFunctionType(tp: Type)(implicit ctx: Context) =
929+
isNonDepFunctionType(tp.dropDependentRefinement)
929930

930931
// Specialized type parameters defined for scala.Function{0,1,2}.
931932
private lazy val Function1SpecializedParams: collection.Set[Type] =

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

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1328,7 +1328,10 @@ object Types {
13281328
val funType = defn.FunctionOf(
13291329
formals1 mapConserve (_.underlyingIfRepeated(mt.isJavaMethod)),
13301330
mt.nonDependentResultApprox, mt.isImplicitMethod && !ctx.erasedTypes)
1331-
if (mt.isDependent && !mt.isImplicitMethod) RefinedType(funType, nme.apply, mt)
1331+
if (mt.isDependent) {
1332+
assert(!mt.isImplicitMethod)
1333+
RefinedType(funType, nme.apply, mt)
1334+
}
13321335
else funType
13331336
}
13341337

@@ -2590,7 +2593,7 @@ object Types {
25902593
def integrate(tparams: List[ParamInfo], tp: Type)(implicit ctx: Context): Type =
25912594
tparams match {
25922595
case LambdaParam(lam, _) :: _ => tp.subst(lam, this)
2593-
case tparams: List[Symbol @unchecked] => tp.subst(tparams, paramRefs)
2596+
case params: List[Symbol @unchecked] => tp.subst(params, paramRefs)
25942597
}
25952598

25962599
final def derivedLambdaType(paramNames: List[ThisName] = this.paramNames,
@@ -2697,7 +2700,7 @@ object Types {
26972700
* def f(x: C)(y: x.S) // dependencyStatus = TrueDeps
26982701
* def f(x: C)(y: x.T) // dependencyStatus = FalseDeps, i.e.
26992702
* // dependency can be eliminated by dealiasing.
2700-
*/
2703+
*/
27012704
private def dependencyStatus(implicit ctx: Context): DependencyStatus = {
27022705
if (myDependencyStatus != Unknown) myDependencyStatus
27032706
else {
@@ -3220,8 +3223,10 @@ object Types {
32203223
case _ => false
32213224
}
32223225

3226+
protected def kindString: String
3227+
32233228
override def toString =
3224-
try s"ParamRef($paramName)"
3229+
try s"${kindString}ParamRef($paramName)"
32253230
catch {
32263231
case ex: IndexOutOfBoundsException => s"ParamRef(<bad index: $paramNum>)"
32273232
}
@@ -3230,8 +3235,9 @@ object Types {
32303235
/** Only created in `binder.paramRefs`. Use `binder.paramRefs(paramNum)` to
32313236
* refer to `TermParamRef(binder, paramNum)`.
32323237
*/
3233-
abstract case class TermParamRef(binder: TermLambda, paramNum: Int) extends ParamRef {
3238+
abstract case class TermParamRef(binder: TermLambda, paramNum: Int) extends ParamRef with SingletonType {
32343239
type BT = TermLambda
3240+
def kindString = "Term"
32353241
def copyBoundType(bt: BT) = bt.paramRefs(paramNum)
32363242
}
32373243

@@ -3240,6 +3246,7 @@ object Types {
32403246
*/
32413247
abstract case class TypeParamRef(binder: TypeLambda, paramNum: Int) extends ParamRef {
32423248
type BT = TypeLambda
3249+
def kindString = "Type"
32433250
def copyBoundType(bt: BT) = bt.paramRefs(paramNum)
32443251

32453252
/** Looking only at the structure of `bound`, is one of the following true?

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -684,7 +684,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
684684
}
685685

686686
private def decomposeProtoFunction(pt: Type, defaultArity: Int)(implicit ctx: Context): (List[Type], Type) = pt match {
687-
case _ if defn.isFunctionType(pt) =>
687+
case _ if defn.isNonDepFunctionType(pt) =>
688688
// if expected parameter type(s) are wildcards, approximate from below.
689689
// if expected result type is a wildcard, approximate from above.
690690
// this can type the greatest set of admissible closures.
@@ -895,7 +895,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
895895
case mt: MethodType =>
896896
pt match {
897897
case SAMType(meth)
898-
if !defn.isFunctionType(pt.dealias.dropDependentRefinement) && mt <:< meth.info =>
898+
if !defn.isFunctionType(pt) && mt <:< meth.info =>
899899
if (!isFullyDefined(pt, ForceDegree.all))
900900
ctx.error(ex"result type of closure is an underspecified SAM type $pt", tree.pos)
901901
TypeTree(pt)

tests/pos/depfuntype.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,6 @@ object Test {
1313
val depfun3: DF = depfun2
1414

1515
val d: C = c
16-
val z = depfun1(d)
16+
val z = depfun3(d)
1717
val z1: d.M = z
1818
}

0 commit comments

Comments
 (0)