aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core/Types.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2014-11-17 11:46:56 +0100
committerMartin Odersky <odersky@gmail.com>2014-11-24 14:56:08 +0100
commit4df3d2a36162f99ade57e209ce432733e082d2a5 (patch)
tree699ab1d59dccf055d39ef68671d3df17be050b09 /src/dotty/tools/dotc/core/Types.scala
parent38b2a61e3dba6160292943a481ccf2b85a695ba7 (diff)
downloaddotty-4df3d2a36162f99ade57e209ce432733e082d2a5.tar.gz
dotty-4df3d2a36162f99ade57e209ce432733e082d2a5.tar.bz2
dotty-4df3d2a36162f99ade57e209ce432733e082d2a5.zip
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.
Diffstat (limited to 'src/dotty/tools/dotc/core/Types.scala')
-rw-r--r--src/dotty/tools/dotc/core/Types.scala117
1 files changed, 48 insertions, 69 deletions
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index 333252010..b7ccd88b0 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -722,7 +722,7 @@ object Types {
/** A prefix-less termRef to a new skolem symbol that has the given type as info */
def narrow(implicit ctx: Context): TermRef = TermRef(NoPrefix, ctx.newSkolem(this))
- // ----- Normalizing typerefs over refined types ----------------------------
+ // ----- Normalizing typerefs over refined types ----------------------------
/** If this is a refinement type that has a refinement for `name` (which might be followed
* by other refinements), and the refined info is a type alias, return the alias,
@@ -733,58 +733,58 @@ object Types {
* to just U. Does not perform the reduction if the resulting type would contain
* a reference to the "this" of the current refined type.
*/
- def lookupRefined(name: Name)(implicit ctx: Context): Type = stripTypeVar match {
- case pre: RefinedType =>
- def dependsOnThis(tp: Type): Boolean = tp match {
- case tp @ TypeRef(RefinedThis(rt), _) if rt refines pre =>
- tp.info match {
- case TypeBounds(lo, hi) if lo eq hi => dependsOnThis(hi)
- case _ => true
- }
- case RefinedThis(rt) =>
- rt refines pre
- case _ => false
- }
- if (pre.refinedName ne name)
- pre.parent.lookupRefined(name)
- else pre.refinedInfo match {
- case TypeBounds(lo, hi) if lo eq hi =>
- if (hi.existsPart(dependsOnThis)) NoType else hi
- case _ => NoType
- }
- case RefinedThis(rt) =>
- rt.lookupRefined(name)
- case pre: WildcardType =>
- WildcardType
- case _ =>
- NoType
+ def lookupRefined(name: Name)(implicit ctx: Context): Type = {
+
+ def dependsOnRefinedThis(tp: Type): Boolean = tp.stripTypeVar match {
+ case tp @ TypeRef(RefinedThis(rt), _) if rt refines this =>
+ tp.info match {
+ case TypeBounds(lo, hi) if lo eq hi => dependsOnRefinedThis(hi)
+ case _ => true
+ }
+ case RefinedThis(rt) => rt refines this
+ case tp: NamedType =>
+ !tp.symbol.isStatic && dependsOnRefinedThis(tp.prefix)
+ case tp: RefinedType => dependsOnRefinedThis(tp.refinedInfo) || dependsOnRefinedThis(tp.parent)
+ case tp: TypeBounds => dependsOnRefinedThis(tp.lo) || dependsOnRefinedThis(tp.hi)
+ case tp: AnnotatedType => dependsOnRefinedThis(tp.underlying)
+ case tp: AndOrType => dependsOnRefinedThis(tp.tp1) || dependsOnRefinedThis(tp.tp2)
+ case _ => false
+ }
+
+ def loop(pre: Type): Type = pre.stripTypeVar match {
+ case pre: RefinedType =>
+ if (pre.refinedName ne name) loop(pre.parent)
+ else this.member(name).info match {
+ case TypeBounds(lo, hi) if (lo eq hi) && !dependsOnRefinedThis(hi) => hi
+ case _ => NoType
+ }
+ case RefinedThis(rt) =>
+ rt.lookupRefined(name)
+ case pre: WildcardType =>
+ WildcardType
+ case _ =>
+ NoType
+ }
+
+ loop(this)
}
/** The type <this . name> , reduced if possible */
def select(name: Name)(implicit ctx: Context): Type = name match {
- case name: TermName =>
- TermRef.all(this, name)
- case name: TypeName =>
- val res = lookupRefined(name)
- if (res.exists) res else TypeRef(this, name)
+ case name: TermName => TermRef.all(this, name)
+ case name: TypeName => TypeRef(this, name).reduceProjection
}
/** The type <this . name> , reduced if possible, with given denotation if unreduced */
def select(name: Name, denot: Denotation)(implicit ctx: Context): Type = name match {
- case name: TermName =>
- TermRef(this, name, denot)
- case name: TypeName =>
- val res = lookupRefined(name)
- if (res.exists) res else TypeRef(this, name, denot)
+ case name: TermName => TermRef(this, name, denot)
+ case name: TypeName => TypeRef(this, name, denot).reduceProjection
}
/** The type <this . name> with given symbol, reduced if possible */
def select(sym: Symbol)(implicit ctx: Context): Type =
if (sym.isTerm) TermRef(this, sym.asTerm)
- else {
- val res = lookupRefined(sym.name)
- if (res.exists) res else TypeRef(this, sym.asType)
- }
+ else TypeRef(this, sym.asType).reduceProjection
// ----- Access to parts --------------------------------------------
@@ -1309,37 +1309,16 @@ object Types {
if (name.isInheritedName) prefix.nonPrivateMember(name.revertInherited)
else prefix.member(name)
- /** Reduce a type-ref `T { X = U; ... } # X` to `U`
+ /** (1) Reduce a type-ref `W # X` or `W { ... } # U`, where `W` is a wildcard type
+ * to an (unbounded) wildcard type.
+ *
+ * (2) Reduce a type-ref `T { X = U; ... } # X` to `U`
* provided `U` does not refer with a RefinedThis to the
- * refinement type `T { X = U; ... }`.
+ * refinement type `T { X = U; ... }`
*/
- def reduceProjection(implicit ctx: Context) =
- if (projectsRefinement(prefix))
- info match {
- case TypeBounds(lo, hi) if (lo eq hi) && !dependsOnRefinedThis(hi) => hi
- case _ => this
- }
- else this
-
- private def projectsRefinement(tp: Type)(implicit ctx: Context): Boolean = tp.stripTypeVar match {
- case tp: RefinedType => (tp.refinedName eq name) || projectsRefinement(tp.parent)
- case _ => false
- }
-
- private def dependsOnRefinedThis(tp: Type)(implicit ctx: Context): Boolean = tp.stripTypeVar match {
- case tp @ TypeRef(RefinedThis(rt), _) if rt refines prefix =>
- tp.info match {
- case TypeBounds(lo, hi) if lo eq hi => dependsOnRefinedThis(hi)
- case _ => true
- }
- case RefinedThis(rt) => rt refines prefix
- case tp: NamedType =>
- !tp.symbol.isStatic && dependsOnRefinedThis(tp.prefix)
- case tp: RefinedType => dependsOnRefinedThis(tp.refinedInfo) || dependsOnRefinedThis(tp.parent)
- case tp: TypeBounds => dependsOnRefinedThis(tp.lo) || dependsOnRefinedThis(tp.hi)
- case tp: AnnotatedType => dependsOnRefinedThis(tp.underlying)
- case tp: AndOrType => dependsOnRefinedThis(tp.tp1) || dependsOnRefinedThis(tp.tp2)
- case _ => false
+ def reduceProjection(implicit ctx: Context): Type = {
+ val reduced = prefix.lookupRefined(name)
+ if (reduced.exists) reduced else this
}
def symbol(implicit ctx: Context): Symbol = {