diff options
author | Paul Phillips <paulp@improving.org> | 2013-09-12 13:28:06 -0700 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2013-09-13 02:42:37 -0700 |
commit | 671e6e03c7e096eda0c27262ae8605fa7af76f59 (patch) | |
tree | b415fb7915ec80503605387b6ccd2ab29d9887a2 /src/reflect | |
parent | 33a819f61b8b9c19708e8ae22bf25adf6cc7ac24 (diff) | |
download | scala-671e6e03c7e096eda0c27262ae8605fa7af76f59.tar.gz scala-671e6e03c7e096eda0c27262ae8605fa7af76f59.tar.bz2 scala-671e6e03c7e096eda0c27262ae8605fa7af76f59.zip |
Corrects behavior of finalResultType.
The implementation had come to depend on finalResultType
accidentally doing things beyond its charter - in particular,
widening types. After hunting down and fixing the call sites
depending on the bugs, I was able to rewrite the method to do
only what it's supposed to do.
I threw in a different way of writing it entirely to suggest how
some correctness might be obtained in the future. It's a lot
harder for a method written like this to break.
Diffstat (limited to 'src/reflect')
-rw-r--r-- | src/reflect/scala/reflect/internal/Definitions.scala | 13 | ||||
-rw-r--r-- | src/reflect/scala/reflect/internal/Trees.scala | 2 | ||||
-rw-r--r-- | src/reflect/scala/reflect/internal/Types.scala | 9 |
3 files changed, 15 insertions, 9 deletions
diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala index 90a1ab39d5..c56637874c 100644 --- a/src/reflect/scala/reflect/internal/Definitions.scala +++ b/src/reflect/scala/reflect/internal/Definitions.scala @@ -695,6 +695,19 @@ trait Definitions extends api.StandardDefinitions { case NullaryMethodType(restpe) => restpe case _ => tp } + + /** An implementation of finalResultType which does only what + * finalResultType is documented to do. Defining it externally to + * Type helps ensure people can't come to depend on accidental + * aspects of its behavior. This is all of it! + */ + def finalResultType(tp: Type): Type = tp match { + case PolyType(_, restpe) => finalResultType(restpe) + case MethodType(_, restpe) => finalResultType(restpe) + case NullaryMethodType(restpe) => finalResultType(restpe) + case _ => tp + } + def abstractFunctionForFunctionType(tp: Type) = { assert(isFunctionType(tp), tp) abstractFunctionType(tp.typeArgs.init, tp.typeArgs.last) diff --git a/src/reflect/scala/reflect/internal/Trees.scala b/src/reflect/scala/reflect/internal/Trees.scala index 84818a6f42..63d66b18dc 100644 --- a/src/reflect/scala/reflect/internal/Trees.scala +++ b/src/reflect/scala/reflect/internal/Trees.scala @@ -1048,7 +1048,7 @@ trait Trees extends api.Trees { self: SymbolTable => sym.name.toTermName, sym.typeParams map TypeDef, vparamss, - TypeTree(sym.tpe.finalResultType) setPos sym.pos.focus, + TypeTree(sym.tpe_*.finalResultType.widen) setPos sym.pos.focus, rhs) setSymbol sym } diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala index ad9001ca4e..3adbbf13fc 100644 --- a/src/reflect/scala/reflect/internal/Types.scala +++ b/src/reflect/scala/reflect/internal/Types.scala @@ -144,7 +144,6 @@ trait Types override def isErroneous = underlying.isErroneous override def isStable: Boolean = underlying.isStable override def isVolatile = underlying.isVolatile - override def finalResultType = underlying.finalResultType override def paramSectionCount = underlying.paramSectionCount override def paramss = underlying.paramss override def params = underlying.params @@ -189,7 +188,6 @@ trait Types override def deconst = maybeRewrap(underlying.deconst) override def resultType = maybeRewrap(underlying.resultType) override def resultType(actuals: List[Type]) = maybeRewrap(underlying.resultType(actuals)) - override def finalResultType = maybeRewrap(underlying.finalResultType) override def paramSectionCount = 0 override def paramss: List[List[Symbol]] = List() override def params: List[Symbol] = List() @@ -440,7 +438,7 @@ trait Types /** For a curried/nullary method or poly type its non-method result type, * the type itself for all other types */ - def finalResultType: Type = this + final def finalResultType: Type = definitions finalResultType this /** For a method type, the number of its value parameter sections, * 0 for all other types */ @@ -1240,7 +1238,6 @@ trait Types if (pre.isOmittablePrefix) pre.fullName + ".type" else prefixString + "type" } - /* override def typeOfThis: Type = typeSymbol.typeOfThis override def bounds: TypeBounds = TypeBounds(this, this) @@ -2564,8 +2561,6 @@ trait Types //TODO this may be generalised so that the only constraint is dependencies are acyclic def approximate: MethodType = MethodType(params, resultApprox) - override def finalResultType: Type = resultType.finalResultType - override def safeToString = paramString(this) + resultType override def cloneInfo(owner: Symbol) = { @@ -2592,7 +2587,6 @@ trait Types override def isTrivial = resultType.isTrivial && (resultType eq resultType.withoutAnnotations) override def prefix: Type = resultType.prefix override def narrow: Type = resultType.narrow - override def finalResultType: Type = resultType.finalResultType override def termSymbol: Symbol = resultType.termSymbol override def typeSymbol: Symbol = resultType.typeSymbol override def parents: List[Type] = resultType.parents @@ -2642,7 +2636,6 @@ trait Types override def baseType(clazz: Symbol): Type = resultType.baseType(clazz) override def narrow: Type = resultType.narrow override def isVolatile = resultType.isVolatile - override def finalResultType: Type = resultType.finalResultType /** @M: typeDefSig wraps a TypeBounds in a PolyType * to represent a higher-kinded type parameter |