Skip to content

Commit 0f4c852

Browse files
committed
Make reduceProjection use lookupRefined
Needed some fixes to lookup refined. The potential alias type is now calculated by taking the member of the original refined type, instead of by simply following the refined info. This takes into account refinements that were defined after the refinement type that contains the alias. The change amde another test (transform) hit the deep subtype limit, which is now disabled.
1 parent dae0c06 commit 0f4c852

File tree

2 files changed

+49
-70
lines changed

2 files changed

+49
-70
lines changed

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

Lines changed: 48 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -713,7 +713,7 @@ object Types {
713713
/** A prefix-less termRef to a new skolem symbol that has the given type as info */
714714
def narrow(implicit ctx: Context): TermRef = TermRef(NoPrefix, ctx.newSkolem(this))
715715

716-
// ----- Normalizing typerefs over refined types ----------------------------
716+
// ----- Normalizing typerefs over refined types ----------------------------
717717

718718
/** If this is a refinement type that has a refinement for `name` (which might be followed
719719
* by other refinements), and the refined info is a type alias, return the alias,
@@ -724,58 +724,58 @@ object Types {
724724
* to just U. Does not perform the reduction if the resulting type would contain
725725
* a reference to the "this" of the current refined type.
726726
*/
727-
def lookupRefined(name: Name)(implicit ctx: Context): Type = stripTypeVar match {
728-
case pre: RefinedType =>
729-
def dependsOnThis(tp: Type): Boolean = tp match {
730-
case tp @ TypeRef(RefinedThis(rt), _) if rt refines pre =>
731-
tp.info match {
732-
case TypeBounds(lo, hi) if lo eq hi => dependsOnThis(hi)
733-
case _ => true
734-
}
735-
case RefinedThis(rt) =>
736-
rt refines pre
737-
case _ => false
738-
}
739-
if (pre.refinedName ne name)
740-
pre.parent.lookupRefined(name)
741-
else pre.refinedInfo match {
742-
case TypeBounds(lo, hi) if lo eq hi =>
743-
if (hi.existsPart(dependsOnThis)) NoType else hi
744-
case _ => NoType
745-
}
746-
case RefinedThis(rt) =>
747-
rt.lookupRefined(name)
748-
case pre: WildcardType =>
749-
WildcardType
750-
case _ =>
751-
NoType
727+
def lookupRefined(name: Name)(implicit ctx: Context): Type = {
728+
729+
def dependsOnRefinedThis(tp: Type): Boolean = tp.stripTypeVar match {
730+
case tp @ TypeRef(RefinedThis(rt), _) if rt refines this =>
731+
tp.info match {
732+
case TypeBounds(lo, hi) if lo eq hi => dependsOnRefinedThis(hi)
733+
case _ => true
734+
}
735+
case RefinedThis(rt) => rt refines this
736+
case tp: NamedType =>
737+
!tp.symbol.isStatic && dependsOnRefinedThis(tp.prefix)
738+
case tp: RefinedType => dependsOnRefinedThis(tp.refinedInfo) || dependsOnRefinedThis(tp.parent)
739+
case tp: TypeBounds => dependsOnRefinedThis(tp.lo) || dependsOnRefinedThis(tp.hi)
740+
case tp: AnnotatedType => dependsOnRefinedThis(tp.underlying)
741+
case tp: AndOrType => dependsOnRefinedThis(tp.tp1) || dependsOnRefinedThis(tp.tp2)
742+
case _ => false
743+
}
744+
745+
def loop(pre: Type): Type = pre.stripTypeVar match {
746+
case pre: RefinedType =>
747+
if (pre.refinedName ne name) loop(pre.parent)
748+
else this.member(name).info match {
749+
case TypeBounds(lo, hi) if (lo eq hi) && !dependsOnRefinedThis(hi) => hi
750+
case _ => NoType
751+
}
752+
case RefinedThis(rt) =>
753+
rt.lookupRefined(name)
754+
case pre: WildcardType =>
755+
WildcardType
756+
case _ =>
757+
NoType
758+
}
759+
760+
loop(this)
752761
}
753762

754763
/** The type <this . name> , reduced if possible */
755764
def select(name: Name)(implicit ctx: Context): Type = name match {
756-
case name: TermName =>
757-
TermRef.all(this, name)
758-
case name: TypeName =>
759-
val res = lookupRefined(name)
760-
if (res.exists) res else TypeRef(this, name)
765+
case name: TermName => TermRef.all(this, name)
766+
case name: TypeName => TypeRef(this, name).reduceProjection
761767
}
762768

763769
/** The type <this . name> , reduced if possible, with given denotation if unreduced */
764770
def select(name: Name, denot: Denotation)(implicit ctx: Context): Type = name match {
765-
case name: TermName =>
766-
TermRef(this, name, denot)
767-
case name: TypeName =>
768-
val res = lookupRefined(name)
769-
if (res.exists) res else TypeRef(this, name, denot)
771+
case name: TermName => TermRef(this, name, denot)
772+
case name: TypeName => TypeRef(this, name, denot).reduceProjection
770773
}
771774

772775
/** The type <this . name> with given symbol, reduced if possible */
773776
def select(sym: Symbol)(implicit ctx: Context): Type =
774777
if (sym.isTerm) TermRef(this, sym.asTerm)
775-
else {
776-
val res = lookupRefined(sym.name)
777-
if (res.exists) res else TypeRef(this, sym.asType)
778-
}
778+
else TypeRef(this, sym.asType).reduceProjection
779779

780780
// ----- Access to parts --------------------------------------------
781781

@@ -1300,37 +1300,16 @@ object Types {
13001300
if (name.isInheritedName) prefix.nonPrivateMember(name.revertInherited)
13011301
else prefix.member(name)
13021302

1303-
/** Reduce a type-ref `T { X = U; ... } # X` to `U`
1303+
/** (1) Reduce a type-ref `W # X` or `W { ... } # U`, where `W` is a wildcard type
1304+
* to an (unbounded) wildcard type.
1305+
*
1306+
* (2) Reduce a type-ref `T { X = U; ... } # X` to `U`
13041307
* provided `U` does not refer with a RefinedThis to the
1305-
* refinement type `T { X = U; ... }`.
1308+
* refinement type `T { X = U; ... }`
13061309
*/
1307-
def reduceProjection(implicit ctx: Context) =
1308-
if (projectsRefinement(prefix))
1309-
info match {
1310-
case TypeBounds(lo, hi) if (lo eq hi) && !dependsOnRefinedThis(hi) => hi
1311-
case _ => this
1312-
}
1313-
else this
1314-
1315-
private def projectsRefinement(tp: Type)(implicit ctx: Context): Boolean = tp.stripTypeVar match {
1316-
case tp: RefinedType => (tp.refinedName eq name) || projectsRefinement(tp.parent)
1317-
case _ => false
1318-
}
1319-
1320-
private def dependsOnRefinedThis(tp: Type)(implicit ctx: Context): Boolean = tp.stripTypeVar match {
1321-
case tp @ TypeRef(RefinedThis(rt), _) if rt refines prefix =>
1322-
tp.info match {
1323-
case TypeBounds(lo, hi) if lo eq hi => dependsOnRefinedThis(hi)
1324-
case _ => true
1325-
}
1326-
case RefinedThis(rt) => rt refines prefix
1327-
case tp: NamedType =>
1328-
!tp.symbol.isStatic && dependsOnRefinedThis(tp.prefix)
1329-
case tp: RefinedType => dependsOnRefinedThis(tp.refinedInfo) || dependsOnRefinedThis(tp.parent)
1330-
case tp: TypeBounds => dependsOnRefinedThis(tp.lo) || dependsOnRefinedThis(tp.hi)
1331-
case tp: AnnotatedType => dependsOnRefinedThis(tp.underlying)
1332-
case tp: AndOrType => dependsOnRefinedThis(tp.tp1) || dependsOnRefinedThis(tp.tp2)
1333-
case _ => false
1310+
def reduceProjection(implicit ctx: Context): Type = {
1311+
val reduced = prefix.lookupRefined(name)
1312+
if (reduced.exists) reduced else this
13341313
}
13351314

13361315
def symbol(implicit ctx: Context): Symbol = {

test/dotc/tests.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ class tests extends CompilerTest {
112112
@Test def dotc_config = compileDir(dotcDir + "tools/dotc/config", twice)
113113
@Test def dotc_core = compileDir(dotcDir + "tools/dotc/core", twice)(allowDeepSubtypes)
114114
@Test def dotc_core_pickling = compileDir(dotcDir + "tools/dotc/core/pickling", twice)(allowDeepSubtypes)
115-
@Test def dotc_transform = compileDir(dotcDir + "tools/dotc/transform", twice)
115+
@Test def dotc_transform = compileDir(dotcDir + "tools/dotc/transform", twice)(allowDeepSubtypes)
116116
@Test def dotc_parsing = compileDir(dotcDir + "tools/dotc/parsing", twice)
117117
@Test def dotc_printing = compileDir(dotcDir + "tools/dotc/printing", twice)
118118
@Test def dotc_reporting = compileDir(dotcDir + "tools/dotc/reporting", twice)

0 commit comments

Comments
 (0)