aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2015-01-09 17:21:38 +0100
committerMartin Odersky <odersky@gmail.com>2015-01-09 17:41:48 +0100
commit710e40e991db4c1c519cfea1d3112b558ad044e9 (patch)
treef53343c7686b732d49b92de89c3802a229485fd7 /src
parentacb64b27c1142b1bf538585347784106fab83767 (diff)
downloaddotty-710e40e991db4c1c519cfea1d3112b558ad044e9.tar.gz
dotty-710e40e991db4c1c519cfea1d3112b558ad044e9.tar.bz2
dotty-710e40e991db4c1c519cfea1d3112b558ad044e9.zip
Made refinement subtype fastpath insensitive to RefineedThis#binder.
Since the binder field in RefinedTypes should not be significant for subtyping, we need to substitute RefinedThis types away before comparing refinements. But this substitution is only done in the slow path. The fix falls back to the slow path if a refinement refers to the refined type via a refined this.
Diffstat (limited to 'src')
-rw-r--r--src/dotty/tools/dotc/config/Config.scala2
-rw-r--r--src/dotty/tools/dotc/core/TypeComparer.scala17
2 files changed, 13 insertions, 6 deletions
diff --git a/src/dotty/tools/dotc/config/Config.scala b/src/dotty/tools/dotc/config/Config.scala
index 317c52633..29d5f7922 100644
--- a/src/dotty/tools/dotc/config/Config.scala
+++ b/src/dotty/tools/dotc/config/Config.scala
@@ -47,7 +47,7 @@ object Config {
final val verboseExplainSubtype = true
/** If this flag is set, take the fast path when comparing same-named type-aliases and types */
- final val fastPathForRefinedSubtype = false
+ final val fastPathForRefinedSubtype = true
/** When set, use new signature-based matching.
* Advantantage of doing so: It's supposed to be faster
diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala
index dfa12826e..83068ab31 100644
--- a/src/dotty/tools/dotc/core/TypeComparer.scala
+++ b/src/dotty/tools/dotc/core/TypeComparer.scala
@@ -787,13 +787,19 @@ class TypeComparer(initctx: Context) extends DotClass with Skolemization {
}
/** Skip refinements in `tp2` which match corresponding refinements in `tp1`.
- * "Match" means: They appear in the same order, refine the same names, and
- * the refinement in `tp1` is an alias type.
+ * "Match" means:
+ * - they appear in the same order,
+ * - they refine the same names,
+ * - the refinement in `tp1` is an alias type, and
+ * - neither refinement refers back to the refined type via a refined this.
* @return The parent type of `tp2` after skipping the matching refinements.
*/
- private def skipMatching(tp1w: Type, tp2: RefinedType): Type = tp1w match {
- case tp1w @ RefinedType(parent1, name1)
- if name1 == tp2.refinedName && tp1w.refinedInfo.isInstanceOf[TypeAlias] =>
+ private def skipMatching(tp1: Type, tp2: RefinedType): Type = tp1 match {
+ case tp1 @ RefinedType(parent1, name1)
+ if name1 == tp2.refinedName &&
+ tp1.refinedInfo.isInstanceOf[TypeAlias] &&
+ !tp2.refinementRefersToThis &&
+ !tp1.refinementRefersToThis =>
tp2.parent match {
case parent2: RefinedType => skipMatching(parent1, parent2)
case parent2 => parent2
@@ -805,6 +811,7 @@ class TypeComparer(initctx: Context) extends DotClass with Skolemization {
* up to parent type `limit`?
* @pre `tp1` has the necessary number of refinements, they are type aliases,
* and their names match the corresponding refinements in `tp2`.
+ * Further, no refinement refers back to the refined type via a refined this.
* The precondition is established by `skipMatching`.
*/
private def isSubRefinements(tp1: RefinedType, tp2: RefinedType, limit: Type): Boolean =