Skip to content

Commit 31cd178

Browse files
committed
Re-use SkolemType for arguments
There are at least two instances where we might skolemize the type of an argument. One is in safeSubstParams when we compute a result type of a dependent method type application. The other is in constrainIfDependentParamRef where we constrain type variables representing dependent parameters. This used to give several skolem types that ended up in a common OrType. We now store computed skolem types in attachments of argument types and re-use them if possible.
1 parent 0ee4c20 commit 31cd178

File tree

3 files changed

+21
-4
lines changed

3 files changed

+21
-4
lines changed

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import Decorators._
1313
import config.Printers.{gadts, typr}
1414
import annotation.tailrec
1515
import reporting.*
16+
import TypeAssigner.skolemizeArgType
1617
import collection.mutable
1718
import scala.annotation.internal.sharable
1819

@@ -853,7 +854,8 @@ trait Inferencing { this: Typer =>
853854
val arg = findArg(call)
854855
if !arg.isEmpty then
855856
var argType = arg.tpe.widenIfUnstable
856-
if !argType.isSingleton then argType = SkolemType(argType)
857+
if !argType.isSingleton then
858+
argType = skolemizeArgType(argType, arg)
857859
argType <:< tvar
858860
case _ =>
859861
end constrainIfDependentParamRef

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

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,7 @@ trait TypeAssigner {
277277
def safeSubstParam(tp: Type, pref: ParamRef, argType: Type, arg: Tree | Null = null)(using Context): Type = {
278278
val tp1 = tp.substParam(pref, argType)
279279
if (tp1 eq tp) || argType.isStable then tp1
280-
else tp.substParam(pref, SkolemType(argType.widen))
280+
else tp.substParam(pref, skolemizeArgType(argType.widen, arg))
281281
}
282282

283283
/** Substitute types of all arguments `args` for corresponding `params` in `tp`.
@@ -574,7 +574,22 @@ object TypeAssigner extends TypeAssigner:
574574
/** An attachment on an argument in an application indicating that the argument's
575575
* type was converted to the given skolem type.
576576
*/
577-
private[typer] val Skolemized = new Property.StickyKey[SkolemType]
577+
private val Skolemized = new Property.StickyKey[SkolemType]
578+
579+
/** A skolem type wrapping `argType`, associated with `arg` if it is non-null.
580+
* Skolem types for the same arguments with equal underlying `argType`s are re-used.
581+
*/
582+
def skolemizeArgType(argType: Type, arg: tpd.Tree | Null)(using Context): Type =
583+
if arg == null then
584+
SkolemType(argType)
585+
else
586+
arg.getAttachment(Skolemized) match
587+
case Some(sk @ SkolemType(tp)) if argType frozen_=:= tp =>
588+
sk
589+
case _ =>
590+
val sk = SkolemType(argType)
591+
arg.putAttachment(Skolemized, sk)
592+
sk
578593

579594
def seqLitType(tree: untpd.SeqLiteral, elemType: Type)(using Context) = tree match
580595
case tree: untpd.JavaSeqLiteral => defn.ArrayOf(elemType)

tests/pending/pos/i23489.scala renamed to tests/pos/i23489.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,4 @@ def Test = ()
1010

1111
val _: Box1[? <: Int] = x
1212

13-
val y = Box2(id(readInt())) // error
13+
val y = Box2(id(readInt()))

0 commit comments

Comments
 (0)