aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core/Types.scala
diff options
context:
space:
mode:
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 = {