aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/ast/Desugar.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/dotty/tools/dotc/ast/Desugar.scala')
-rw-r--r--src/dotty/tools/dotc/ast/Desugar.scala42
1 files changed, 35 insertions, 7 deletions
diff --git a/src/dotty/tools/dotc/ast/Desugar.scala b/src/dotty/tools/dotc/ast/Desugar.scala
index 1aab16469..05f652a39 100644
--- a/src/dotty/tools/dotc/ast/Desugar.scala
+++ b/src/dotty/tools/dotc/ast/Desugar.scala
@@ -834,17 +834,45 @@ object desugar {
}
}.withPos(tree.pos)
- /** Create a class definition with the same info as this refined type.
+ /** Create a class definition with the same info as the refined type given by `parent`
+ * and `refinements`.
+ *
* parent { refinements }
* ==>
- * trait <refinement> extends parent { refinements }
+ * trait <refinement> extends core { this: self => refinements }
+ *
+ * Here, `core` is the (possibly parameterized) class part of `parent`.
+ * If `parent` is the same as `core`, self is empty. Otherwise `self` is `parent`.
+ *
+ * Example: Given
+ *
+ * class C
+ * type T1 extends C { type T <: A }
+ *
+ * the refined type
*
- * If the parent is missing, Object is assumed.
- * The result is used for validity checking, is thrown away afterwards.
+ * T1 { type T <: B }
+ *
+ * is expanded to
+ *
+ * trait <refinement> extends C { this: T1 => type T <: A }
+ *
+ * The result of this method is used for validity checking, is thrown away afterwards.
+ * @param parentType The type of `parent`
*/
- def refinedTypeToClass(tree: RefinedTypeTree)(implicit ctx: Context): TypeDef = {
- val parent = if (tree.tpt.isEmpty) TypeTree(defn.ObjectType) else tree.tpt
- val impl = Template(emptyConstructor, parent :: Nil, EmptyValDef, tree.refinements)
+ def refinedTypeToClass(parent: tpd.Tree, refinements: List[Tree])(implicit ctx: Context): TypeDef = {
+ def stripToCore(tp: Type): Type = tp match {
+ case tp: RefinedType if tp.argInfos.nonEmpty => tp // parameterized class type
+ case tp: TypeRef if tp.symbol.isClass => tp // monomorphic class type
+ case tp: TypeProxy => stripToCore(tp.underlying)
+ case _ => defn.AnyType
+ }
+ val parentCore = stripToCore(parent.tpe)
+ val untpdParent = TypedSplice(parent)
+ val (classParent, self) =
+ if (parent.tpe eq parentCore) (untpdParent, EmptyValDef)
+ else (TypeTree(parentCore), ValDef(nme.WILDCARD, untpdParent, EmptyTree))
+ val impl = Template(emptyConstructor, classParent :: Nil, self, refinements)
TypeDef(tpnme.REFINE_CLASS, impl).withFlags(Trait)
}