Skip to content

Commit bf3b50a

Browse files
committed
Strip opaque refinement in widening
We only care about the opaque refinement in member selection. By stripping the opaque alias in widening, the compiler avoids doing useless work.
1 parent f7e0d31 commit bf3b50a

File tree

2 files changed

+26
-4
lines changed

2 files changed

+26
-4
lines changed

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

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -769,7 +769,7 @@ object Types {
769769
tycon.derivedLambdaAbstraction(tycon.paramNames, tycon.paramInfos, info).appliedTo(tp.args))
770770

771771
def goThis(tp: ThisType) =
772-
val underlying = tp.underlying
772+
val underlying = tp.underlying(withOpaque = true)
773773
val d = go(underlying)
774774
if d.exists then
775775
if underlying.isInstanceOf[AndType] then
@@ -2694,10 +2694,14 @@ object Types {
26942694
case _ if ctx.mode.is(Mode.Interactive) => defn.AnyClass // was observed to happen in IDE mode
26952695
}
26962696

2697-
override def underlying(using Context): Type =
2697+
override def underlying(using Context): Type = underlying(withOpaque = false)
2698+
2699+
final def underlying(withOpaque: Boolean)(using Context): Type =
26982700
if (ctx.erasedTypes) tref
26992701
else cls.info match {
2700-
case cinfo: ClassInfo => cinfo.selfType
2702+
case cinfo: ClassInfo =>
2703+
if withOpaque then cinfo.selfType
2704+
else cinfo.selfTypeWithoutOpaque
27012705
case _: ErrorType | NoType if ctx.mode.is(Mode.Interactive) => cls.info
27022706
// can happen in IDE if `cls` is stale
27032707
}
@@ -4548,6 +4552,7 @@ object Types {
45484552

45494553
private var selfTypeCache: Type = null
45504554
private var appliedRefCache: Type = null
4555+
private var selfTypeWithoutOpaqueCache: Type = null
45514556

45524557
/** The self type of a class is the conjunction of
45534558
* - the explicit self type if given (or the info of a given self symbol), and
@@ -4566,6 +4571,23 @@ object Types {
45664571
selfTypeCache
45674572
}
45684573

4574+
/** The self type without opaque members refinements */
4575+
def selfTypeWithoutOpaque(using Context): Type = {
4576+
def dropRefinement(tp: Type): Type = tp match
4577+
case RefinedType(parent, _, _: TypeAlias) =>
4578+
// TODO: maybe strengthen the check for Opaque flag
4579+
parent
4580+
case AndType(tp1, tp2) =>
4581+
AndType(dropRefinement(tp1), dropRefinement(tp2))
4582+
case _ =>
4583+
tp
4584+
end dropRefinement
4585+
4586+
if selfTypeWithoutOpaqueCache == null then
4587+
selfTypeWithoutOpaqueCache = dropRefinement(selfType)
4588+
selfTypeWithoutOpaqueCache
4589+
}
4590+
45694591
def appliedRef(using Context): Type = {
45704592
if (appliedRefCache == null)
45714593
appliedRefCache =

tests/run/option-extract.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ enum Option[+A]:
66
opaque type ExtractResult[B] = (=> B) => B
77

88
def extract[B](f: A => B): ExtractResult[B] =
9-
def result(default: => B): B = (this: Option[A]) match
9+
def result(default: => B): B = this match
1010
case None => default
1111
case Some(elem) => f(elem)
1212
result

0 commit comments

Comments
 (0)