Skip to content

Commit 36cd9b5

Browse files
committed
Handle FunProtos in wildcard approximations
That way we can cache implicit searches involving FunProtos in the required types.
1 parent 3ba9821 commit 36cd9b5

File tree

1 file changed

+36
-1
lines changed

1 file changed

+36
-1
lines changed

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

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,13 @@ object ProtoTypes {
324324
def typedArgs: List[Tree] = typedArgs(force = true)
325325
def unforcedTypedArgs: List[Tree] = typedArgs(force = false)
326326

327+
private def unforcedArgType(arg: untpd.Tree)(implicit ctx: Context): Type = {
328+
val targ = state.typedArg(arg)
329+
if (targ != null) targ.tpe else WildcardType
330+
}
331+
332+
def unforcedArgTypes(implicit ctx: Context) = args.map(unforcedArgType)
333+
327334
/** Type single argument and remember the unadapted result in `myTypedArg`.
328335
* used to avoid repeated typings of trees when backtracking.
329336
*/
@@ -393,6 +400,32 @@ object ProtoTypes {
393400
override def withContext(ctx: Context): FunProtoTyped = this
394401
}
395402

403+
/** A wildcard approximation of FunProtos used in implicit search */
404+
abstract class WildFunProto(argTypes: List[Type], resType: Type)
405+
extends CachedGroundType with ProtoType {
406+
407+
def isMatchedBy(tp: Type, keepConstraint: Boolean = false)(implicit ctx: Context): Boolean = true
408+
409+
def fold[T](x: T, ta: TypeAccumulator[T])(implicit ctx: Context): T =
410+
ta(ta.foldOver(x, argTypes), resType)
411+
412+
def map(tm: TypeMap)(implicit ctx: Context): ProtoType =
413+
derivedWildFunProto(argTypes.mapconserve(tm), tm(resType))
414+
415+
def derivedWildFunProto(argTypes: List[Type], resType: Type)(implicit ctx: Context) =
416+
if ((argTypes `eq` this.argTypes) && (resType `eq` this.resType)) this
417+
else WildFunProto(argTypes, resType)
418+
}
419+
420+
class CachedWildFunProto(argTypes: List[Type], resultType: Type) extends WildFunProto(argTypes, resultType) {
421+
override def computeHash(bs: Hashable.Binders): Int = doHash(bs, argTypes, resultType)
422+
}
423+
424+
object WildFunProto {
425+
def apply(argTypes: List[Type], resType: Type)(implicit ctx: Context) =
426+
unique(new CachedWildFunProto(argTypes, resType))
427+
}
428+
396429
/** A prototype for implicitly inferred views:
397430
*
398431
* []: argType => resultType
@@ -661,7 +694,9 @@ object ProtoTypes {
661694
wildApprox(tp.argType, theMap, seen),
662695
wildApprox(tp.resultType, theMap, seen))
663696
case tp: FunProto =>
664-
WildcardType
697+
WildFunProto(
698+
tp.unforcedArgTypes.mapConserve(wildApprox(_, theMap, seen)),
699+
wildApprox(tp.resType, theMap, seen))
665700
case _: ThisType | _: BoundType => // default case, inlined for speed
666701
tp
667702
case _ =>

0 commit comments

Comments
 (0)