Skip to content

Commit ac5bac0

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 ac5bac0

File tree

1 file changed

+38
-1
lines changed

1 file changed

+38
-1
lines changed

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

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

327+
/** The types of all arguments that are already known at this point.
328+
* WildcardType for the others.
329+
*/
330+
def unforcedArgTypes(implicit ctx: Context): List[Type] =
331+
for (arg <- args) yield {
332+
val targ = state.typedArg(arg)
333+
if (targ != null) targ.tpe else WildcardType
334+
}
335+
327336
/** Type single argument and remember the unadapted result in `myTypedArg`.
328337
* used to avoid repeated typings of trees when backtracking.
329338
*/
@@ -393,6 +402,32 @@ object ProtoTypes {
393402
override def withContext(ctx: Context): FunProtoTyped = this
394403
}
395404

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

0 commit comments

Comments
 (0)