Skip to content

Commit 17ef71d

Browse files
committed
Some bugfixes and added functionality to support implicits.
1 parent 8115e09 commit 17ef71d

File tree

1 file changed

+50
-17
lines changed

1 file changed

+50
-17
lines changed

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

Lines changed: 50 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,48 @@ object Applications {
2525

2626
private val isNamedArg = (arg: Any) => arg.isInstanceOf[Trees.NamedArg[_]]
2727
def hasNamedArg(args: List[Any]) = args exists isNamedArg
28+
29+
/** A trait defining an `isCompatible` method. */
30+
trait Compatibility {
31+
32+
/** Is there an implicit conversion from `tp` to `pt`? */
33+
def viewExists(tp: Type, pt: Type)(implicit ctx: Context): Boolean
34+
35+
/** A type `tp` is compatible with a type `pt` if one of the following holds:
36+
* 1. `tp` is a subtype of `pt`
37+
* 2. `pt` is by name parameter type, and `tp` is compatible with its underlying type
38+
* 3. there is an implicit conversion from `tp` to `pt`.
39+
*/
40+
def isCompatible(tp: Type, pt: Type)(implicit ctx: Context): Boolean = (
41+
tp <:< pt
42+
|| pt.typeSymbol == defn.ByNameParamClass && tp <:< pt.typeArgs.head
43+
|| viewExists(tp, pt)
44+
)
45+
}
46+
47+
/** A trait defining a `normalize` method. */
48+
trait Normalizing {
49+
50+
/** The normalized form of a type
51+
* - unwraps polymorphic types, tracking their parameters in the current constraint
52+
* - skips implicit parameters
53+
* - converts non-dependent method types to the corresponding function types
54+
* - dereferences parameterless method types
55+
*/
56+
def normalize(tp: Type)(implicit ctx: Context): Type = tp.widen match {
57+
case pt: PolyType => normalize(ctx.track(pt).resultType)
58+
case mt: MethodType if !mt.isDependent =>
59+
if (mt.isImplicit) mt.resultType
60+
else defn.FunctionType(mt.paramTypes, mt.resultType)
61+
case et: ExprType => et.resultType
62+
case _ => tp
63+
}
64+
}
2865
}
2966

30-
trait Applications { self: Typer =>
67+
import Applications._
68+
69+
trait Applications extends Compatibility with Normalizing { self: Typer =>
3170

3271
import Applications._
3372
import Trees._
@@ -66,21 +105,6 @@ trait Applications { self: Typer =>
66105
tree
67106
}
68107

69-
def normalize(tp: Type)(implicit ctx: Context) = tp.widen match {
70-
case pt: PolyType => ctx.track(pt).resultType
71-
case mt: MethodType if !mt.isDependent =>
72-
if (mt.isImplicit) mt.resultType
73-
else defn.FunctionType(mt.paramTypes, mt.resultType)
74-
case et: ExprType => et.resultType
75-
case _ => tp
76-
}
77-
78-
def isCompatible(tp: Type, pt: Type)(implicit ctx: Context): Boolean = (
79-
tp <:< pt
80-
|| pt.typeSymbol == defn.ByNameParamClass && tp <:< pt.typeArgs.head
81-
|| viewExists(tp, pt)
82-
)
83-
84108
/**
85109
* @param Arg the type of arguments, could be tpd.Tree, untpd.Tree, or Type
86110
* @param methRef the reference to the method of the application
@@ -492,6 +516,12 @@ trait Applications { self: Typer =>
492516
def treeToArg(arg: tpd.Tree): tpd.Tree = arg
493517
}
494518

519+
def typedApply(app: untpd.Apply, fun: tpd.Tree, methRef: TermRef, args: List[tpd.Tree], resultType: Type)(implicit ctx: Context): tpd.Tree =
520+
new ApplyToTyped(app, fun, methRef, args, resultType).result
521+
522+
def typedApply(fun: tpd.Tree, methRef: TermRef, args: List[tpd.Tree], resultType: Type)(implicit ctx: Context): tpd.Tree =
523+
typedApply(Apply(untpd.TypedSplice(fun), Nil), fun, methRef, args, resultType)
524+
495525
/** Is given method reference applicable to argument types `args`?
496526
* @param resultType The expected result type of the application
497527
*/
@@ -580,6 +610,9 @@ trait Applications { self: Typer =>
580610
best :: asGood(alts1)
581611
}
582612

613+
private val dummyTree = Literal(Constant(null))
614+
def dummyTreeOfType(tp: Type): tpd.Tree = dummyTree withType tp
615+
583616
/** Resolve overloaded alternative `alts`, given expected type `pt`. */
584617
def resolveOverloaded(alts: List[TermRef], pt: Type)(implicit ctx: Context): List[TermRef] = {
585618

@@ -601,7 +634,7 @@ trait Applications { self: Typer =>
601634
val argShape = treeShape(arg)
602635
tree.withType(argShape.tpe).derivedNamedArg(name, argShape)
603636
case _ =>
604-
Literal(Constant(null)) withType typeShape(tree)
637+
dummyTreeOfType(typeShape(tree))
605638
}
606639

607640
def narrowByTypes(alts: List[TermRef], argTypes: List[Type], resultType: Type): List[TermRef] =

0 commit comments

Comments
 (0)