diff options
author | Martin Odersky <odersky@gmail.com> | 2015-01-09 17:21:38 +0100 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2015-01-09 17:41:48 +0100 |
commit | 710e40e991db4c1c519cfea1d3112b558ad044e9 (patch) | |
tree | f53343c7686b732d49b92de89c3802a229485fd7 /src | |
parent | acb64b27c1142b1bf538585347784106fab83767 (diff) | |
download | dotty-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.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/TypeComparer.scala | 17 |
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 = |