Skip to content

Commit f444573

Browse files
authored
Merge pull request #9230 from dotty-staging/fix-#9224
Fix #9224: Refine stopAtStatic criterion
2 parents ba501f4 + 7bd84e1 commit f444573

File tree

3 files changed

+29
-15
lines changed

3 files changed

+29
-15
lines changed

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,14 @@ object TypeOps:
389389
@threadUnsafe lazy val forbidden = symsToAvoid.toSet
390390
def toAvoid(sym: Symbol) = !sym.isStatic && forbidden.contains(sym)
391391
def partsToAvoid = new NamedPartsAccumulator(tp => toAvoid(tp.symbol))
392+
393+
/** True iff all NamedTypes on this prefix are static */
394+
override def isStaticPrefix(pre: Type)(using Context): Boolean = pre match
395+
case pre: NamedType =>
396+
val sym = pre.currentSymbol
397+
sym.is(Package) || sym.isStatic && isStaticPrefix(pre.prefix)
398+
case _ => true
399+
392400
def apply(tp: Type): Type = tp match {
393401
case tp: TermRef
394402
if toAvoid(tp.symbol) || partsToAvoid(mutable.Set.empty, tp.info).nonEmpty =>

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

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4850,7 +4850,7 @@ object Types {
48504850
// ----- TypeMaps --------------------------------------------------------------------
48514851

48524852
/** Common base class of TypeMap and TypeAccumulator */
4853-
abstract class VariantTraversal {
4853+
abstract class VariantTraversal:
48544854
protected[core] var variance: Int = 1
48554855

48564856
inline protected def atVariance[T](v: Int)(op: => T): T = {
@@ -4860,13 +4860,22 @@ object Types {
48604860
variance = saved
48614861
res
48624862
}
4863-
}
4863+
4864+
protected def stopAtStatic: Boolean = true
4865+
4866+
/** Can the prefix of this static reference be omitted if the reference
4867+
* itself can be omitted? Overridden in TypeOps#avoid.
4868+
*/
4869+
protected def isStaticPrefix(pre: Type)(using Context): Boolean = true
4870+
4871+
protected def stopBecauseStaticOrLocal(tp: NamedType)(using Context): Boolean =
4872+
(tp.prefix eq NoPrefix)
4873+
|| stopAtStatic && tp.currentSymbol.isStatic && isStaticPrefix(tp.prefix)
4874+
end VariantTraversal
48644875

48654876
abstract class TypeMap(implicit protected var mapCtx: Context)
48664877
extends VariantTraversal with (Type => Type) { thisMap =>
48674878

4868-
protected def stopAtStatic: Boolean = true
4869-
48704879
def apply(tp: Type): Type
48714880

48724881
protected def derivedSelect(tp: NamedType, pre: Type): Type =
@@ -4912,8 +4921,8 @@ object Types {
49124921
implicit val ctx = this.mapCtx
49134922
tp match {
49144923
case tp: NamedType =>
4915-
if (stopAtStatic && tp.symbol.isStatic || (tp.prefix `eq` NoPrefix)) tp
4916-
else {
4924+
if stopBecauseStaticOrLocal(tp) then tp
4925+
else
49174926
val prefix1 = atVariance(variance max 0)(this(tp.prefix))
49184927
// A prefix is never contravariant. Even if say `p.A` is used in a contravariant
49194928
// context, we cannot assume contravariance for `p` because `p`'s lower
@@ -4922,7 +4931,6 @@ object Types {
49224931
// if `p <: q` then `p.A <: q.A`, and well-formedness requires that `A` is a member
49234932
// of `p`'s upper bound.
49244933
derivedSelect(tp, prefix1)
4925-
}
49264934
case _: ThisType
49274935
| _: BoundType
49284936
| NoPrefix => tp
@@ -5077,7 +5085,6 @@ object Types {
50775085
}
50785086

50795087
@sharable object IdentityTypeMap extends TypeMap()(NoContext) {
5080-
override def stopAtStatic: Boolean = true
50815088
def apply(tp: Type): Type = tp
50825089
}
50835090

@@ -5334,8 +5341,6 @@ object Types {
53345341
abstract class TypeAccumulator[T](implicit protected val accCtx: Context)
53355342
extends VariantTraversal with ((T, Type) => T) {
53365343

5337-
protected def stopAtStatic: Boolean = true
5338-
53395344
def apply(x: T, tp: Type): T
53405345

53415346
protected def applyToAnnot(x: T, annot: Annotation): T = x // don't go into annotations
@@ -5348,11 +5353,10 @@ object Types {
53485353
record(s"foldOver total")
53495354
tp match {
53505355
case tp: TypeRef =>
5351-
if (stopAtStatic && tp.symbol.isStatic || (tp.prefix `eq` NoPrefix)) x
5352-
else {
5356+
if stopBecauseStaticOrLocal(tp) then x
5357+
else
53535358
val tp1 = tp.prefix.lookupRefined(tp.name)
53545359
if (tp1.exists) this(x, tp1) else applyToPrefix(x, tp)
5355-
}
53565360

53575361
case tp @ AppliedType(tycon, args) =>
53585362
@tailrec def foldArgs(x: T, tparams: List[ParamInfo], args: List[Type]): T =
@@ -5378,8 +5382,7 @@ object Types {
53785382
this(y, restpe)
53795383

53805384
case tp: TermRef =>
5381-
if (stopAtStatic && tp.currentSymbol.isStatic || (tp.prefix `eq` NoPrefix)) x
5382-
else applyToPrefix(x, tp)
5385+
if stopBecauseStaticOrLocal(tp) then x else applyToPrefix(x, tp)
53835386

53845387
case tp: TypeVar =>
53855388
this(x, tp.underlying)

tests/pos/i9224.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
object foo { def test = 23 }
2+
3+
def bar(x: Any) = x match { case m: foo.type => m.test } // need to call m.test

0 commit comments

Comments
 (0)