Skip to content

Commit 71d3b36

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 0dbce7d commit 71d3b36

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
@@ -692,7 +692,7 @@ object Types {
692692
/** A prefix-less termRef to a new skolem symbol that has the given type as info */
693693
def narrow(implicit ctx: Context): TermRef = TermRef(NoPrefix, ctx.newSkolem(this))
694694

695-
// ----- Normalizing typerefs over refined types ----------------------------
695+
// ----- Normalizing typerefs over refined types ----------------------------
696696

697697
/** If this is a refinement type that has a refinement for `name` (which might be followed
698698
* by other refinements), and the refined info is a type alias, return the alias,
@@ -703,58 +703,58 @@ object Types {
703703
* to just U. Does not perform the reduction if the resulting type would contain
704704
* a reference to the "this" of the current refined type.
705705
*/
706-
def lookupRefined(name: Name)(implicit ctx: Context): Type = stripTypeVar match {
707-
case pre: RefinedType =>
708-
def dependsOnThis(tp: Type): Boolean = tp match {
709-
case tp @ TypeRef(RefinedThis(rt), _) if rt refines pre =>
710-
tp.info match {
711-
case TypeBounds(lo, hi) if lo eq hi => dependsOnThis(hi)
712-
case _ => true
713-
}
714-
case RefinedThis(rt) =>
715-
rt refines pre
716-
case _ => false
717-
}
718-
if (pre.refinedName ne name)
719-
pre.parent.lookupRefined(name)
720-
else pre.refinedInfo match {
721-
case TypeBounds(lo, hi) if lo eq hi =>
722-
if (hi.existsPart(dependsOnThis)) NoType else hi
723-
case _ => NoType
724-
}
725-
case RefinedThis(rt) =>
726-
rt.lookupRefined(name)
727-
case pre: WildcardType =>
728-
WildcardType
729-
case _ =>
730-
NoType
706+
def lookupRefined(name: Name)(implicit ctx: Context): Type = {
707+
708+
def dependsOnRefinedThis(tp: Type): Boolean = tp.stripTypeVar match {
709+
case tp @ TypeRef(RefinedThis(rt), _) if rt refines this =>
710+
tp.info match {
711+
case TypeBounds(lo, hi) if lo eq hi => dependsOnRefinedThis(hi)
712+
case _ => true
713+
}
714+
case RefinedThis(rt) => rt refines this
715+
case tp: NamedType =>
716+
!tp.symbol.isStatic && dependsOnRefinedThis(tp.prefix)
717+
case tp: RefinedType => dependsOnRefinedThis(tp.refinedInfo) || dependsOnRefinedThis(tp.parent)
718+
case tp: TypeBounds => dependsOnRefinedThis(tp.lo) || dependsOnRefinedThis(tp.hi)
719+
case tp: AnnotatedType => dependsOnRefinedThis(tp.underlying)
720+
case tp: AndOrType => dependsOnRefinedThis(tp.tp1) || dependsOnRefinedThis(tp.tp2)
721+
case _ => false
722+
}
723+
724+
def loop(pre: Type): Type = pre.stripTypeVar match {
725+
case pre: RefinedType =>
726+
if (pre.refinedName ne name) loop(pre.parent)
727+
else this.member(name).info match {
728+
case TypeBounds(lo, hi) if (lo eq hi) && !dependsOnRefinedThis(hi) => hi
729+
case _ => NoType
730+
}
731+
case RefinedThis(rt) =>
732+
rt.lookupRefined(name)
733+
case pre: WildcardType =>
734+
WildcardType
735+
case _ =>
736+
NoType
737+
}
738+
739+
loop(this)
731740
}
732741

733742
/** The type <this . name> , reduced if possible */
734743
def select(name: Name)(implicit ctx: Context): Type = name match {
735-
case name: TermName =>
736-
TermRef.all(this, name)
737-
case name: TypeName =>
738-
val res = lookupRefined(name)
739-
if (res.exists) res else TypeRef(this, name)
744+
case name: TermName => TermRef.all(this, name)
745+
case name: TypeName => TypeRef(this, name).reduceProjection
740746
}
741747

742748
/** The type <this . name> , reduced if possible, with given denotation if unreduced */
743749
def select(name: Name, denot: Denotation)(implicit ctx: Context): Type = name match {
744-
case name: TermName =>
745-
TermRef(this, name, denot)
746-
case name: TypeName =>
747-
val res = lookupRefined(name)
748-
if (res.exists) res else TypeRef(this, name, denot)
750+
case name: TermName => TermRef(this, name, denot)
751+
case name: TypeName => TypeRef(this, name, denot).reduceProjection
749752
}
750753

751754
/** The type <this . name> with given symbol, reduced if possible */
752755
def select(sym: Symbol)(implicit ctx: Context): Type =
753756
if (sym.isTerm) TermRef(this, sym.asTerm)
754-
else {
755-
val res = lookupRefined(sym.name)
756-
if (res.exists) res else TypeRef(this, sym.asType)
757-
}
757+
else TypeRef(this, sym.asType).reduceProjection
758758

759759
// ----- Access to parts --------------------------------------------
760760

@@ -1279,37 +1279,16 @@ object Types {
12791279
if (name.isInheritedName) prefix.nonPrivateMember(name.revertInherited)
12801280
else prefix.member(name)
12811281

1282-
/** Reduce a type-ref `T { X = U; ... } # X` to `U`
1282+
/** (1) Reduce a type-ref `W # X` or `W { ... } # U`, where `W` is a wildcard type
1283+
* to an (unbounded) wildcard type.
1284+
*
1285+
* (2) Reduce a type-ref `T { X = U; ... } # X` to `U`
12831286
* provided `U` does not refer with a RefinedThis to the
1284-
* refinement type `T { X = U; ... }`.
1287+
* refinement type `T { X = U; ... }`
12851288
*/
1286-
def reduceProjection(implicit ctx: Context) =
1287-
if (projectsRefinement(prefix))
1288-
info match {
1289-
case TypeBounds(lo, hi) if (lo eq hi) && !dependsOnRefinedThis(hi) => hi
1290-
case _ => this
1291-
}
1292-
else this
1293-
1294-
private def projectsRefinement(tp: Type)(implicit ctx: Context): Boolean = tp.stripTypeVar match {
1295-
case tp: RefinedType => (tp.refinedName eq name) || projectsRefinement(tp.parent)
1296-
case _ => false
1297-
}
1298-
1299-
private def dependsOnRefinedThis(tp: Type)(implicit ctx: Context): Boolean = tp.stripTypeVar match {
1300-
case tp @ TypeRef(RefinedThis(rt), _) if rt refines prefix =>
1301-
tp.info match {
1302-
case TypeBounds(lo, hi) if lo eq hi => dependsOnRefinedThis(hi)
1303-
case _ => true
1304-
}
1305-
case RefinedThis(rt) => rt refines prefix
1306-
case tp: NamedType =>
1307-
!tp.symbol.isStatic && dependsOnRefinedThis(tp.prefix)
1308-
case tp: RefinedType => dependsOnRefinedThis(tp.refinedInfo) || dependsOnRefinedThis(tp.parent)
1309-
case tp: TypeBounds => dependsOnRefinedThis(tp.lo) || dependsOnRefinedThis(tp.hi)
1310-
case tp: AnnotatedType => dependsOnRefinedThis(tp.underlying)
1311-
case tp: AndOrType => dependsOnRefinedThis(tp.tp1) || dependsOnRefinedThis(tp.tp2)
1312-
case _ => false
1289+
def reduceProjection(implicit ctx: Context): Type = {
1290+
val reduced = prefix.lookupRefined(name)
1291+
if (reduced.exists) reduced else this
13131292
}
13141293

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

test/dotc/tests.scala

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

0 commit comments

Comments
 (0)