aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core/TypeOps.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/dotty/tools/dotc/core/TypeOps.scala')
-rw-r--r--src/dotty/tools/dotc/core/TypeOps.scala86
1 files changed, 57 insertions, 29 deletions
diff --git a/src/dotty/tools/dotc/core/TypeOps.scala b/src/dotty/tools/dotc/core/TypeOps.scala
index 1288c0b23..80e0fc6f1 100644
--- a/src/dotty/tools/dotc/core/TypeOps.scala
+++ b/src/dotty/tools/dotc/core/TypeOps.scala
@@ -6,6 +6,7 @@ import Contexts._, Types._, Symbols._, Names._, Flags._, Scopes._
import SymDenotations._, Denotations.SingleDenotation
import config.Printers._
import util.Positions._
+import NameOps._
import Decorators._
import StdNames._
import Annotations._
@@ -193,10 +194,7 @@ trait TypeOps { this: Context => // TODO: Make standalone object.
case tp: RefinedType => isClassRef(tp.parent)
case _ => false
}
- def next(tp: TypeProxy) = tp.underlying match {
- case TypeBounds(_, hi) => hi
- case nx => nx
- }
+
/** If `tp1` and `tp2` are typebounds, try to make one fit into the other
* or to make them equal, by instantiating uninstantiated type variables.
*/
@@ -226,19 +224,24 @@ trait TypeOps { this: Context => // TODO: Make standalone object.
return tp1.derivedRefinedType(
approximateUnion(OrType(tp1.parent, tp2.parent)),
tp1.refinedName,
- homogenizedUnion(tp1.refinedInfo, tp2.refinedInfo).substRefinedThis(tp2, RefinedThis(tp1)))
+ homogenizedUnion(tp1.refinedInfo, tp2.refinedInfo))
//.ensuring { x => println(i"approx or $tp1 | $tp2 = $x\n constr = ${ctx.typerState.constraint}"); true } // DEBUG
case _ =>
}
case _ =>
}
+
tp1 match {
+ case tp1: RecType =>
+ tp1.rebind(approximateOr(tp1.parent, tp2))
case tp1: TypeProxy if !isClassRef(tp1) =>
- approximateUnion(next(tp1) | tp2)
+ approximateUnion(tp1.superType | tp2)
case _ =>
tp2 match {
+ case tp2: RecType =>
+ tp2.rebind(approximateOr(tp1, tp2.parent))
case tp2: TypeProxy if !isClassRef(tp2) =>
- approximateUnion(tp1 | next(tp2))
+ approximateUnion(tp1 | tp2.superType)
case _ =>
val commonBaseClasses = tp.mapReduceOr(_.baseClasses)(intersect)
val doms = dominators(commonBaseClasses, Nil)
@@ -252,16 +255,32 @@ trait TypeOps { this: Context => // TODO: Make standalone object.
if (ctx.featureEnabled(defn.LanguageModuleClass, nme.keepUnions)) tp
else tp match {
case tp: OrType =>
- approximateOr(tp.tp1, tp.tp2)
+ approximateOr(tp.tp1, tp.tp2) // Maybe refactor using liftToRec?
case tp @ AndType(tp1, tp2) =>
tp derived_& (approximateUnion(tp1), approximateUnion(tp2))
case tp: RefinedType =>
tp.derivedRefinedType(approximateUnion(tp.parent), tp.refinedName, tp.refinedInfo)
+ case tp: RecType =>
+ tp.rebind(approximateUnion(tp.parent))
case _ =>
tp
}
}
+ /** Not currently needed:
+ *
+ def liftToRec(f: (Type, Type) => Type)(tp1: Type, tp2: Type)(implicit ctx: Context) = {
+ def f2(tp1: Type, tp2: Type): Type = tp2 match {
+ case tp2: RecType => tp2.rebind(f(tp1, tp2.parent))
+ case _ => f(tp1, tp2)
+ }
+ tp1 match {
+ case tp1: RecType => tp1.rebind(f2(tp1.parent, tp2))
+ case _ => f2(tp1, tp2)
+ }
+ }
+ */
+
private def enterArgBinding(formal: Symbol, info: Type, cls: ClassSymbol, decls: Scope) = {
val lazyInfo = new LazyType { // needed so we do not force `formal`.
def complete(denot: SymDenotation)(implicit ctx: Context): Unit = {
@@ -361,28 +380,37 @@ trait TypeOps { this: Context => // TODO: Make standalone object.
var formals: SimpleMap[TypeName, Symbol] = SimpleMap.Empty // A map of all formal parent parameter
// Strip all refinements from parent type, populating `refinements` and `formals` maps.
- def normalizeToRef(tp: Type): TypeRef = tp.dealias match {
- case tp: TypeRef =>
- tp
- case tp @ RefinedType(tp1, name: TypeName) =>
- tp.refinedInfo match {
- case TypeAlias(TypeRef(pre, name1)) if name1 == name && (pre =:= cls.thisType) =>
- // Don't record refinements of the form X = this.X (These can arise using named parameters).
- typr.println(s"dropping refinement $tp")
- case _ =>
- val prevInfo = refinements(name)
- refinements = refinements.updated(name,
- if (prevInfo == null) tp.refinedInfo else prevInfo & tp.refinedInfo)
- formals = formals.updated(name, tp1.typeParamNamed(name))
- }
- normalizeToRef(tp1)
- case ErrorType =>
- defn.AnyType
- case AnnotatedType(tpe, _) =>
- normalizeToRef(tpe)
- case _ =>
- throw new TypeError(s"unexpected parent type: $tp")
+ def normalizeToRef(tp: Type): TypeRef = {
+ def fail = throw new TypeError(s"unexpected parent type: $tp")
+ tp.dealias match {
+ case tp: TypeRef =>
+ tp
+ case tp @ RefinedType(tp1, name: TypeName, rinfo) =>
+ rinfo match {
+ case TypeAlias(TypeRef(pre, name1)) if name1 == name && (pre =:= cls.thisType) =>
+ // Don't record refinements of the form X = this.X (These can arise using named parameters).
+ typr.println(s"dropping refinement $tp")
+ case _ =>
+ val prevInfo = refinements(name)
+ refinements = refinements.updated(name,
+ if (prevInfo == null) tp.refinedInfo else prevInfo & tp.refinedInfo)
+ formals = formals.updated(name, tp1.typeParamNamed(name))
+ }
+ normalizeToRef(tp1)
+ case ErrorType =>
+ defn.AnyType
+ case AnnotatedType(tpe, _) =>
+ normalizeToRef(tpe)
+ case HKApply(tycon: TypeRef, args) =>
+ tycon.info match {
+ case TypeAlias(alias) => normalizeToRef(alias.appliedTo(args))
+ case _ => fail
+ }
+ case _ =>
+ fail
+ }
}
+
val parentRefs = parents map normalizeToRef
// Enter all refinements into current scope.