diff options
author | Martin Odersky <odersky@gmail.com> | 2014-07-22 18:43:24 +0200 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2014-07-22 18:43:24 +0200 |
commit | ababb2ce2675619c997cb4bfa143b454e4076850 (patch) | |
tree | e2d22d801e06e046e2f18a51705eee5d332e1d52 /src | |
parent | e8d2733c3e496d811bb1002418b08ba1abe3ee8b (diff) | |
download | dotty-ababb2ce2675619c997cb4bfa143b454e4076850.tar.gz dotty-ababb2ce2675619c997cb4bfa143b454e4076850.tar.bz2 dotty-ababb2ce2675619c997cb4bfa143b454e4076850.zip |
Defined substitution which follows aliases
Used in FullParameterization to substitute type parameters.
Fixes test failure for t2399.scala
Diffstat (limited to 'src')
-rw-r--r-- | src/dotty/tools/dotc/core/Substituters.scala | 40 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Types.scala | 13 | ||||
-rw-r--r-- | src/dotty/tools/dotc/transform/FullParameterization.scala | 4 |
3 files changed, 49 insertions, 8 deletions
diff --git a/src/dotty/tools/dotc/core/Substituters.scala b/src/dotty/tools/dotc/core/Substituters.scala index 3d14317cb..f5f60e6a5 100644 --- a/src/dotty/tools/dotc/core/Substituters.scala +++ b/src/dotty/tools/dotc/core/Substituters.scala @@ -89,6 +89,40 @@ trait Substituters { this: Context => } } + final def substDealias(tp: Type, from: List[Symbol], to: List[Type], theMap: SubstDealiasMap): Type = { + tp match { + case tp: NamedType => + val sym = tp.symbol + var fs = from + var ts = to + while (fs.nonEmpty) { + if (fs.head eq sym) return ts.head + fs = fs.tail + ts = ts.tail + } + if (sym.isStatic && !existsStatic(from)) tp + else { + val prefix1 = substDealias(tp.prefix, from, to, theMap) + if (prefix1 ne tp.prefix) tp.derivedSelect(prefix1) + else if (sym.isAliasType) { + val hi = sym.info.bounds.hi + val hi1 = substDealias(hi, from, to, theMap) + if (hi1 eq hi) tp else hi1 + } + else tp + } + case _: ThisType | _: BoundType | NoPrefix => + tp + case tp: RefinedType => + tp.derivedRefinedType(substDealias(tp.parent, from, to, theMap), tp.refinedName, substDealias(tp.refinedInfo, from, to, theMap)) + case tp: TypeBounds if tp.lo eq tp.hi => + tp.derivedTypeAlias(substDealias(tp.lo, from, to, theMap)) + case _ => + (if (theMap != null) theMap else new SubstDealiasMap(from, to)) + .mapOver(tp) + } + } + final def substSym(tp: Type, from: List[Symbol], to: List[Symbol], theMap: SubstSymMap): Type = tp match { case tp: NamedType => @@ -205,11 +239,11 @@ trait Substituters { this: Context => final class SubstMap(from: List[Symbol], to: List[Type]) extends DeepTypeMap { def apply(tp: Type): Type = subst(tp, from, to, this) } -/* not needed yet + final class SubstDealiasMap(from: List[Symbol], to: List[Type]) extends SubstMap(from, to) { - override def apply(tp: Type): Type = subst(tp.dealias, from, to, this) + override def apply(tp: Type): Type = substDealias(tp, from, to, this) } -*/ + final class SubstSymMap(from: List[Symbol], to: List[Symbol]) extends DeepTypeMap { def apply(tp: Type): Type = substSym(tp, from, to, this) } diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala index 1d1c326a0..8149cce78 100644 --- a/src/dotty/tools/dotc/core/Types.scala +++ b/src/dotty/tools/dotc/core/Types.scala @@ -818,10 +818,17 @@ object Types { } } -/* Not needed yet: + /** Same as `subst` but follows aliases as a fallback. When faced with a reference + * to an alias type, where normal substiution does not yield a new type, the + * substitution is instead applied to the alias. If that yields a new type, + * this type is returned, outherwise the original type (not the alias) is returned. + * A use case for this method is if one wants to substitute the type parameters + * of a class and also wants to substitute any parameter accessors that alias + * the type parameters. + */ final def substDealias(from: List[Symbol], to: List[Type])(implicit ctx: Context): Type = - new ctx.SubstDealiasMap(from, to).apply(this) -*/ + ctx.substDealias(this, from, to, null) + /** Substitute all types of the form `PolyParam(from, N)` by * `PolyParam(to, N)`. */ diff --git a/src/dotty/tools/dotc/transform/FullParameterization.scala b/src/dotty/tools/dotc/transform/FullParameterization.scala index 3a40f9f3e..cdea5754c 100644 --- a/src/dotty/tools/dotc/transform/FullParameterization.scala +++ b/src/dotty/tools/dotc/transform/FullParameterization.scala @@ -104,7 +104,7 @@ trait FullParameterization { /** Replace class type parameters by the added type parameters of the polytype `pt` */ def mapClassParams(tp: Type, pt: PolyType): Type = { val classParamsRange = (mtparamCount until mtparamCount + ctparams.length).toList - tp.subst(clazz.typeParams, classParamsRange map (PolyParam(pt, _))) + tp.substDealias(clazz.typeParams, classParamsRange map (PolyParam(pt, _))) } /** The bounds for the added type paraneters of the polytype `pt` */ @@ -201,7 +201,7 @@ trait FullParameterization { new TreeTypeMap( typeMap = rewireType(_) - .subst(origTParams, trefs) + .substDealias(origTParams, trefs) .subst(origVParams, argRefs.map(_.tpe)) .substThisUnlessStatic(origClass, thisRef.tpe), ownerMap = (sym => if (sym eq origMeth) derived else sym), |